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 } |