Mercurial > hg > truffle
comparison src/cpu/x86/vm/interp_masm_x86_64.cpp @ 1206:87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
Summary: Fix incorrect marking of methods as not compilable.
Reviewed-by: never
author | kvn |
---|---|
date | Mon, 01 Feb 2010 16:49:49 -0800 |
parents | 85f13cdfbc1d |
children | 576e77447e3c |
comparison
equal
deleted
inserted
replaced
1205:5fcfaa1ad96f | 1206:87684f1a88b5 |
---|---|
1260 Label profile_continue; | 1260 Label profile_continue; |
1261 | 1261 |
1262 // If no method data exists, go to profile_continue. | 1262 // If no method data exists, go to profile_continue. |
1263 test_method_data_pointer(mdp, profile_continue); | 1263 test_method_data_pointer(mdp, profile_continue); |
1264 | 1264 |
1265 // We are making a call. Increment the count. | |
1266 increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); | |
1267 | |
1268 Label skip_receiver_profile; | 1265 Label skip_receiver_profile; |
1269 if (receiver_can_be_null) { | 1266 if (receiver_can_be_null) { |
1267 Label not_null; | |
1270 testptr(receiver, receiver); | 1268 testptr(receiver, receiver); |
1271 jcc(Assembler::zero, skip_receiver_profile); | 1269 jccb(Assembler::notZero, not_null); |
1270 // We are making a call. Increment the count for null receiver. | |
1271 increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); | |
1272 jmp(skip_receiver_profile); | |
1273 bind(not_null); | |
1272 } | 1274 } |
1273 | 1275 |
1274 // Record the receiver type. | 1276 // Record the receiver type. |
1275 record_klass_in_profile(receiver, mdp, reg2); | 1277 record_klass_in_profile(receiver, mdp, reg2, true); |
1276 bind(skip_receiver_profile); | 1278 bind(skip_receiver_profile); |
1277 | 1279 |
1278 // The method data pointer needs to be updated to reflect the new target. | 1280 // The method data pointer needs to be updated to reflect the new target. |
1279 update_mdp_by_constant(mdp, | 1281 update_mdp_by_constant(mdp, |
1280 in_bytes(VirtualCallData:: | 1282 in_bytes(VirtualCallData:: |
1294 // function is recursive, to generate the required tree structured code. | 1296 // function is recursive, to generate the required tree structured code. |
1295 // It's the interpreter, so we are trading off code space for speed. | 1297 // It's the interpreter, so we are trading off code space for speed. |
1296 // See below for example code. | 1298 // See below for example code. |
1297 void InterpreterMacroAssembler::record_klass_in_profile_helper( | 1299 void InterpreterMacroAssembler::record_klass_in_profile_helper( |
1298 Register receiver, Register mdp, | 1300 Register receiver, Register mdp, |
1299 Register reg2, | 1301 Register reg2, int start_row, |
1300 int start_row, Label& done) { | 1302 Label& done, bool is_virtual_call) { |
1301 if (TypeProfileWidth == 0) | 1303 if (TypeProfileWidth == 0) { |
1304 if (is_virtual_call) { | |
1305 increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); | |
1306 } | |
1302 return; | 1307 return; |
1308 } | |
1303 | 1309 |
1304 int last_row = VirtualCallData::row_limit() - 1; | 1310 int last_row = VirtualCallData::row_limit() - 1; |
1305 assert(start_row <= last_row, "must be work left to do"); | 1311 assert(start_row <= last_row, "must be work left to do"); |
1306 // Test this row for both the receiver and for null. | 1312 // Test this row for both the receiver and for null. |
1307 // Take any of three different outcomes: | 1313 // Take any of three different outcomes: |
1325 increment_mdp_data_at(mdp, count_offset); | 1331 increment_mdp_data_at(mdp, count_offset); |
1326 jmp(done); | 1332 jmp(done); |
1327 bind(next_test); | 1333 bind(next_test); |
1328 | 1334 |
1329 if (test_for_null_also) { | 1335 if (test_for_null_also) { |
1336 Label found_null; | |
1330 // Failed the equality check on receiver[n]... Test for null. | 1337 // Failed the equality check on receiver[n]... Test for null. |
1331 testptr(reg2, reg2); | 1338 testptr(reg2, reg2); |
1332 if (start_row == last_row) { | 1339 if (start_row == last_row) { |
1333 // The only thing left to do is handle the null case. | 1340 // The only thing left to do is handle the null case. |
1334 jcc(Assembler::notZero, done); | 1341 if (is_virtual_call) { |
1342 jccb(Assembler::zero, found_null); | |
1343 // Receiver did not match any saved receiver and there is no empty row for it. | |
1344 // Increment total counter to indicate polimorphic case. | |
1345 increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); | |
1346 jmp(done); | |
1347 bind(found_null); | |
1348 } else { | |
1349 jcc(Assembler::notZero, done); | |
1350 } | |
1335 break; | 1351 break; |
1336 } | 1352 } |
1337 // Since null is rare, make it be the branch-taken case. | 1353 // Since null is rare, make it be the branch-taken case. |
1338 Label found_null; | |
1339 jcc(Assembler::zero, found_null); | 1354 jcc(Assembler::zero, found_null); |
1340 | 1355 |
1341 // Put all the "Case 3" tests here. | 1356 // Put all the "Case 3" tests here. |
1342 record_klass_in_profile_helper(receiver, mdp, reg2, start_row + 1, done); | 1357 record_klass_in_profile_helper(receiver, mdp, reg2, start_row + 1, done, is_virtual_call); |
1343 | 1358 |
1344 // Found a null. Keep searching for a matching receiver, | 1359 // Found a null. Keep searching for a matching receiver, |
1345 // but remember that this is an empty (unused) slot. | 1360 // but remember that this is an empty (unused) slot. |
1346 bind(found_null); | 1361 bind(found_null); |
1347 } | 1362 } |
1354 int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row)); | 1369 int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row)); |
1355 set_mdp_data_at(mdp, recvr_offset, receiver); | 1370 set_mdp_data_at(mdp, recvr_offset, receiver); |
1356 int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row)); | 1371 int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row)); |
1357 movl(reg2, DataLayout::counter_increment); | 1372 movl(reg2, DataLayout::counter_increment); |
1358 set_mdp_data_at(mdp, count_offset, reg2); | 1373 set_mdp_data_at(mdp, count_offset, reg2); |
1359 jmp(done); | 1374 if (start_row > 0) { |
1375 jmp(done); | |
1376 } | |
1360 } | 1377 } |
1361 | 1378 |
1362 // Example state machine code for three profile rows: | 1379 // Example state machine code for three profile rows: |
1363 // // main copy of decision tree, rooted at row[1] | 1380 // // main copy of decision tree, rooted at row[1] |
1364 // if (row[0].rec == rec) { row[0].incr(); goto done; } | 1381 // if (row[0].rec == rec) { row[0].incr(); goto done; } |
1366 // // inner copy of decision tree, rooted at row[1] | 1383 // // inner copy of decision tree, rooted at row[1] |
1367 // if (row[1].rec == rec) { row[1].incr(); goto done; } | 1384 // if (row[1].rec == rec) { row[1].incr(); goto done; } |
1368 // if (row[1].rec != NULL) { | 1385 // if (row[1].rec != NULL) { |
1369 // // degenerate decision tree, rooted at row[2] | 1386 // // degenerate decision tree, rooted at row[2] |
1370 // if (row[2].rec == rec) { row[2].incr(); goto done; } | 1387 // if (row[2].rec == rec) { row[2].incr(); goto done; } |
1371 // if (row[2].rec != NULL) { goto done; } // overflow | 1388 // if (row[2].rec != NULL) { count.incr(); goto done; } // overflow |
1372 // row[2].init(rec); goto done; | 1389 // row[2].init(rec); goto done; |
1373 // } else { | 1390 // } else { |
1374 // // remember row[1] is empty | 1391 // // remember row[1] is empty |
1375 // if (row[2].rec == rec) { row[2].incr(); goto done; } | 1392 // if (row[2].rec == rec) { row[2].incr(); goto done; } |
1376 // row[1].init(rec); goto done; | 1393 // row[1].init(rec); goto done; |
1379 // // remember row[0] is empty | 1396 // // remember row[0] is empty |
1380 // if (row[1].rec == rec) { row[1].incr(); goto done; } | 1397 // if (row[1].rec == rec) { row[1].incr(); goto done; } |
1381 // if (row[2].rec == rec) { row[2].incr(); goto done; } | 1398 // if (row[2].rec == rec) { row[2].incr(); goto done; } |
1382 // row[0].init(rec); goto done; | 1399 // row[0].init(rec); goto done; |
1383 // } | 1400 // } |
1401 // done: | |
1384 | 1402 |
1385 void InterpreterMacroAssembler::record_klass_in_profile(Register receiver, | 1403 void InterpreterMacroAssembler::record_klass_in_profile(Register receiver, |
1386 Register mdp, | 1404 Register mdp, Register reg2, |
1387 Register reg2) { | 1405 bool is_virtual_call) { |
1388 assert(ProfileInterpreter, "must be profiling"); | 1406 assert(ProfileInterpreter, "must be profiling"); |
1389 Label done; | 1407 Label done; |
1390 | 1408 |
1391 record_klass_in_profile_helper(receiver, mdp, reg2, 0, done); | 1409 record_klass_in_profile_helper(receiver, mdp, reg2, 0, done, is_virtual_call); |
1392 | 1410 |
1393 bind (done); | 1411 bind (done); |
1394 } | 1412 } |
1395 | 1413 |
1396 void InterpreterMacroAssembler::profile_ret(Register return_bci, | 1414 void InterpreterMacroAssembler::profile_ret(Register return_bci, |
1482 int mdp_delta = in_bytes(BitData::bit_data_size()); | 1500 int mdp_delta = in_bytes(BitData::bit_data_size()); |
1483 if (TypeProfileCasts) { | 1501 if (TypeProfileCasts) { |
1484 mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); | 1502 mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); |
1485 | 1503 |
1486 // Record the object type. | 1504 // Record the object type. |
1487 record_klass_in_profile(klass, mdp, reg2); | 1505 record_klass_in_profile(klass, mdp, reg2, false); |
1488 } | 1506 } |
1489 update_mdp_by_constant(mdp, mdp_delta); | 1507 update_mdp_by_constant(mdp, mdp_delta); |
1490 | 1508 |
1491 bind(profile_continue); | 1509 bind(profile_continue); |
1492 } | 1510 } |