comparison src/cpu/x86/vm/interp_masm_x86_64.cpp @ 9760:c76b43ed5089

Added infrastructure for recording invoked methods in the profiling information.
author Christian Haeubl <haeubl@ssw.jku.at>
date Fri, 17 May 2013 15:38:22 +0200
parents 291ffc492eb6
children 836a62f43af9
comparison
equal deleted inserted replaced
9759:580faa2ee288 9760:c76b43ed5089
1083 1083
1084 // The method data pointer needs to be updated to reflect the new target. 1084 // The method data pointer needs to be updated to reflect the new target.
1085 update_mdp_by_constant(mdp, 1085 update_mdp_by_constant(mdp,
1086 in_bytes(VirtualCallData:: 1086 in_bytes(VirtualCallData::
1087 virtual_call_data_size())); 1087 virtual_call_data_size()));
1088
1088 bind(profile_continue); 1089 bind(profile_continue);
1089 } 1090 }
1090 } 1091 }
1091 1092
1092 1093
1114 // Record the receiver type. 1115 // Record the receiver type.
1115 record_klass_in_profile(receiver, mdp, reg2, true); 1116 record_klass_in_profile(receiver, mdp, reg2, true);
1116 bind(skip_receiver_profile); 1117 bind(skip_receiver_profile);
1117 1118
1118 // The method data pointer needs to be updated to reflect the new target. 1119 // The method data pointer needs to be updated to reflect the new target.
1119 update_mdp_by_constant(mdp, 1120 #ifdef GRAAL
1120 in_bytes(VirtualCallData:: 1121 if (MethodProfileWidth == 0) {
1121 virtual_call_data_size())); 1122 update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size()));
1123 }
1124 #else
1125 update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size()));
1126 #endif
1122 bind(profile_continue); 1127 bind(profile_continue);
1123 } 1128 }
1124 } 1129 }
1130
1131 #ifdef GRAAL
1132 void InterpreterMacroAssembler::profile_called_method(Register method, Register mdp, Register reg2) {
1133 assert_different_registers(method, mdp, reg2);
1134 if (ProfileInterpreter && MethodProfileWidth > 0) {
1135 Label profile_continue;
1136
1137 // If no method data exists, go to profile_continue.
1138 test_method_data_pointer(mdp, profile_continue);
1139
1140 Label done;
1141 record_item_in_profile_helper(method, mdp, reg2, 0, done, MethodProfileWidth,
1142 &VirtualCallData::method_offset, &VirtualCallData::method_count_offset, in_bytes(VirtualCallData::nonprofiled_receiver_count_offset()));
1143 bind (done);
1144
1145 update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size()));
1146 bind(profile_continue);
1147 }
1148 }
1149
1150 #endif
1125 1151
1126 // This routine creates a state machine for updating the multi-row 1152 // This routine creates a state machine for updating the multi-row
1127 // type profile at a virtual call site (or other type-sensitive bytecode). 1153 // type profile at a virtual call site (or other type-sensitive bytecode).
1128 // The machine visits each row (of receiver/count) until the receiver type 1154 // The machine visits each row (of receiver/count) until the receiver type
1129 // is found, or until it runs out of rows. At the same time, it remembers 1155 // is found, or until it runs out of rows. At the same time, it remembers
1134 // function is recursive, to generate the required tree structured code. 1160 // function is recursive, to generate the required tree structured code.
1135 // It's the interpreter, so we are trading off code space for speed. 1161 // It's the interpreter, so we are trading off code space for speed.
1136 // See below for example code. 1162 // See below for example code.
1137 void InterpreterMacroAssembler::record_klass_in_profile_helper( 1163 void InterpreterMacroAssembler::record_klass_in_profile_helper(
1138 Register receiver, Register mdp, 1164 Register receiver, Register mdp,
1139 Register reg2, int start_row, 1165 Register reg2, Label& done, bool is_virtual_call) {
1140 Label& done, bool is_virtual_call) {
1141 if (TypeProfileWidth == 0) { 1166 if (TypeProfileWidth == 0) {
1142 if (is_virtual_call) { 1167 if (is_virtual_call) {
1143 increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); 1168 increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
1144 } 1169 }
1145 #ifdef GRAAL 1170 #ifdef GRAAL
1146 else { 1171 else {
1147 increment_mdp_data_at(mdp, in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset())); 1172 increment_mdp_data_at(mdp, in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset()));
1148 } 1173 }
1149 #endif 1174 #endif
1150 return; 1175 } else {
1151 } 1176 bool use_non_profiled_counter = !is_virtual_call || IS_GRAAL_DEFINED;
1152 1177 int non_profiled_offset = -1;
1153 int last_row = VirtualCallData::row_limit() - 1; 1178 if (use_non_profiled_counter) {
1179 non_profiled_offset = in_bytes(CounterData::count_offset());
1180 #ifdef GRAAL
1181 if (!is_virtual_call) {
1182 non_profiled_offset = in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset());
1183 }
1184 #endif
1185 assert(non_profiled_offset >= 0, "must be");
1186 }
1187
1188 record_item_in_profile_helper(receiver, mdp, reg2, 0, done, TypeProfileWidth,
1189 &VirtualCallData::receiver_offset, &VirtualCallData::receiver_count_offset, non_profiled_offset);
1190 }
1191 }
1192
1193 void InterpreterMacroAssembler::record_item_in_profile_helper(Register item, Register mdp,
1194 Register reg2, int start_row, Label& done, int total_rows,
1195 OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn,
1196 int non_profiled_offset) {
1197 int last_row = total_rows - 1;
1154 assert(start_row <= last_row, "must be work left to do"); 1198 assert(start_row <= last_row, "must be work left to do");
1155 // Test this row for both the receiver and for null. 1199 // Test this row for both the item and for null.
1156 // Take any of three different outcomes: 1200 // Take any of three different outcomes:
1157 // 1. found receiver => increment count and goto done 1201 // 1. found item => increment count and goto done
1158 // 2. found null => keep looking for case 1, maybe allocate this cell 1202 // 2. found null => keep looking for case 1, maybe allocate this cell
1159 // 3. found something else => keep looking for cases 1 and 2 1203 // 3. found something else => keep looking for cases 1 and 2
1160 // Case 3 is handled by a recursive call. 1204 // Case 3 is handled by a recursive call.
1161 for (int row = start_row; row <= last_row; row++) { 1205 for (int row = start_row; row <= last_row; row++) {
1162 Label next_test; 1206 Label next_test;
1163 bool test_for_null_also = (row == start_row); 1207 bool test_for_null_also = (row == start_row);
1164 1208
1165 // See if the receiver is receiver[n]. 1209 // See if the item is item[n].
1166 int recvr_offset = in_bytes(VirtualCallData::receiver_offset(row)); 1210 int item_offset = in_bytes(item_offset_fn(row));
1167 test_mdp_data_at(mdp, recvr_offset, receiver, 1211 test_mdp_data_at(mdp, item_offset, item,
1168 (test_for_null_also ? reg2 : noreg), 1212 (test_for_null_also ? reg2 : noreg),
1169 next_test); 1213 next_test);
1170 // (Reg2 now contains the receiver from the CallData.) 1214 // (Reg2 now contains the item from the CallData.)
1171 1215
1172 // The receiver is receiver[n]. Increment count[n]. 1216 // The item is item[n]. Increment count[n].
1173 int count_offset = in_bytes(VirtualCallData::receiver_count_offset(row)); 1217 int count_offset = in_bytes(item_count_offset_fn(row));
1174 increment_mdp_data_at(mdp, count_offset); 1218 increment_mdp_data_at(mdp, count_offset);
1175 jmp(done); 1219 jmp(done);
1176 bind(next_test); 1220 bind(next_test);
1177 1221
1178 if (test_for_null_also) { 1222 if (test_for_null_also) {
1179 Label found_null; 1223 Label found_null;
1180 // Failed the equality check on receiver[n]... Test for null. 1224 // Failed the equality check on item[n]... Test for null.
1181 testptr(reg2, reg2); 1225 testptr(reg2, reg2);
1182 if (start_row == last_row) { 1226 if (start_row == last_row) {
1183 // The only thing left to do is handle the null case. 1227 // The only thing left to do is handle the null case.
1184 if (is_virtual_call GRAAL_ONLY(|| true)) { 1228 if (non_profiled_offset >= 0) {
1185 jccb(Assembler::zero, found_null); 1229 jccb(Assembler::zero, found_null);
1186 // Receiver did not match any saved receiver and there is no empty row for it. 1230 // Item did not match any saved item and there is no empty row for it.
1187 // Increment total counter to indicate polymorphic case. 1231 // Increment total counter to indicate polymorphic case.
1188 int offset = in_bytes(CounterData::count_offset()); 1232 increment_mdp_data_at(mdp, non_profiled_offset);
1189 #ifdef GRAAL
1190 if (!is_virtual_call) {
1191 offset = in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset());
1192 }
1193 #endif
1194 increment_mdp_data_at(mdp, offset);
1195 jmp(done); 1233 jmp(done);
1196 bind(found_null); 1234 bind(found_null);
1197 } else { 1235 } else {
1198 jcc(Assembler::notZero, done); 1236 jcc(Assembler::notZero, done);
1199 } 1237 }
1201 } 1239 }
1202 // Since null is rare, make it be the branch-taken case. 1240 // Since null is rare, make it be the branch-taken case.
1203 jcc(Assembler::zero, found_null); 1241 jcc(Assembler::zero, found_null);
1204 1242
1205 // Put all the "Case 3" tests here. 1243 // Put all the "Case 3" tests here.
1206 record_klass_in_profile_helper(receiver, mdp, reg2, start_row + 1, done, is_virtual_call); 1244 record_item_in_profile_helper(item, mdp, reg2, start_row + 1, done, total_rows,
1207 1245 item_offset_fn, item_count_offset_fn, non_profiled_offset);
1208 // Found a null. Keep searching for a matching receiver, 1246
1247 // Found a null. Keep searching for a matching item,
1209 // but remember that this is an empty (unused) slot. 1248 // but remember that this is an empty (unused) slot.
1210 bind(found_null); 1249 bind(found_null);
1211 } 1250 }
1212 } 1251 }
1213 1252
1214 // In the fall-through case, we found no matching receiver, but we 1253 // In the fall-through case, we found no matching item, but we
1215 // observed the receiver[start_row] is NULL. 1254 // observed the item[start_row] is NULL.
1216 1255
1217 // Fill in the receiver field and increment the count. 1256 // Fill in the item field and increment the count.
1218 int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row)); 1257 int item_offset = in_bytes(item_offset_fn(start_row));
1219 set_mdp_data_at(mdp, recvr_offset, receiver); 1258 set_mdp_data_at(mdp, item_offset, item);
1220 int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row)); 1259 int count_offset = in_bytes(item_count_offset_fn(start_row));
1221 movl(reg2, DataLayout::counter_increment); 1260 movl(reg2, DataLayout::counter_increment);
1222 set_mdp_data_at(mdp, count_offset, reg2); 1261 set_mdp_data_at(mdp, count_offset, reg2);
1223 if (start_row > 0) { 1262 if (start_row > 0) {
1224 jmp(done); 1263 jmp(done);
1225 } 1264 }
1253 Register mdp, Register reg2, 1292 Register mdp, Register reg2,
1254 bool is_virtual_call) { 1293 bool is_virtual_call) {
1255 assert(ProfileInterpreter, "must be profiling"); 1294 assert(ProfileInterpreter, "must be profiling");
1256 Label done; 1295 Label done;
1257 1296
1258 record_klass_in_profile_helper(receiver, mdp, reg2, 0, done, is_virtual_call); 1297 record_klass_in_profile_helper(receiver, mdp, reg2, done, is_virtual_call);
1259 1298
1260 bind (done); 1299 bind (done);
1261 } 1300 }
1262 1301
1263 void InterpreterMacroAssembler::profile_ret(Register return_bci, 1302 void InterpreterMacroAssembler::profile_ret(Register return_bci,
1308 set_mdp_flag_at(mdp, BitData::null_seen_byte_constant()); 1347 set_mdp_flag_at(mdp, BitData::null_seen_byte_constant());
1309 1348
1310 // The method data pointer needs to be updated. 1349 // The method data pointer needs to be updated.
1311 int mdp_delta = in_bytes(BitData::bit_data_size()); 1350 int mdp_delta = in_bytes(BitData::bit_data_size());
1312 if (TypeProfileCasts) { 1351 if (TypeProfileCasts) {
1313 mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); 1352 mdp_delta = in_bytes(ReceiverTypeData::receiver_type_data_size());
1314 } 1353 }
1315 update_mdp_by_constant(mdp, mdp_delta); 1354 update_mdp_by_constant(mdp, mdp_delta);
1316 1355
1317 bind(profile_continue); 1356 bind(profile_continue);
1318 } 1357 }
1326 // If no method data exists, go to profile_continue. 1365 // If no method data exists, go to profile_continue.
1327 test_method_data_pointer(mdp, profile_continue); 1366 test_method_data_pointer(mdp, profile_continue);
1328 1367
1329 int count_offset = in_bytes(CounterData::count_offset()); 1368 int count_offset = in_bytes(CounterData::count_offset());
1330 // Back up the address, since we have already bumped the mdp. 1369 // Back up the address, since we have already bumped the mdp.
1331 count_offset -= in_bytes(VirtualCallData::virtual_call_data_size()); 1370 count_offset -= in_bytes(ReceiverTypeData::receiver_type_data_size());
1332 1371
1333 // *Decrement* the counter. We expect to see zero or small negatives. 1372 // *Decrement* the counter. We expect to see zero or small negatives.
1334 increment_mdp_data_at(mdp, count_offset, true); 1373 increment_mdp_data_at(mdp, count_offset, true);
1335 1374
1336 bind (profile_continue); 1375 bind (profile_continue);
1346 test_method_data_pointer(mdp, profile_continue); 1385 test_method_data_pointer(mdp, profile_continue);
1347 1386
1348 // The method data pointer needs to be updated. 1387 // The method data pointer needs to be updated.
1349 int mdp_delta = in_bytes(BitData::bit_data_size()); 1388 int mdp_delta = in_bytes(BitData::bit_data_size());
1350 if (TypeProfileCasts) { 1389 if (TypeProfileCasts) {
1351 mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); 1390 mdp_delta = in_bytes(ReceiverTypeData::receiver_type_data_size());
1352 1391
1353 // Record the object type. 1392 // Record the object type.
1354 record_klass_in_profile(klass, mdp, reg2, false); 1393 record_klass_in_profile(klass, mdp, reg2, false);
1355 } 1394 }
1356 update_mdp_by_constant(mdp, mdp_delta); 1395 update_mdp_by_constant(mdp, mdp_delta);