Mercurial > hg > truffle
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); |