202 |
202 |
203 if ((bci >= start) && (bci < end) && (elem->slot == slot)) { |
203 if ((bci >= start) && (bci < end) && (elem->slot == slot)) { |
204 ConstantPool* cp = method->constants(); |
204 ConstantPool* cp = method->constants(); |
205 char *var = cp->symbol_at(elem->name_cp_index)->as_C_string(); |
205 char *var = cp->symbol_at(elem->name_cp_index)->as_C_string(); |
206 if (strlen(var) == 4 && strcmp(var, "this") == 0) { |
206 if (strlen(var) == 4 && strcmp(var, "this") == 0) { |
207 reason.print("loaded from 'this'"); |
207 reason.print("this"); |
208 } else { |
208 } else { |
209 reason.print("loaded from local variable '%s'", var); |
209 reason.print("%s", var); |
210 } |
210 } |
211 |
211 |
212 return TrackingStackSource(TrackingStackSource::LOCAL_VAR, bci, reason.as_string()); |
212 return TrackingStackSource(TrackingStackSource::LOCAL_VAR, bci, reason.as_string()); |
213 } |
213 } |
214 } |
214 } |
215 } |
215 } |
216 |
216 |
217 // Handle at least some cases we know. |
217 // Handle at least some cases we know. |
218 if (!method->is_static() && (slot == 0)) { |
218 if (!method->is_static() && (slot == 0)) { |
219 reason.print("loaded from 'this'"); |
219 reason.print("this"); |
220 } else { |
220 } else { |
221 int curr = method->is_static() ? 0 : 1; |
221 int curr = method->is_static() ? 0 : 1; |
222 SignatureStream ss(method->signature()); |
222 SignatureStream ss(method->signature()); |
223 int param_index = 0; |
223 int param_index = 0; |
224 bool found = false; |
224 bool found = false; |
238 param_index += 1; |
238 param_index += 1; |
239 curr += size; |
239 curr += size; |
240 } |
240 } |
241 |
241 |
242 if (found) { |
242 if (found) { |
243 reason.print("loaded from the parameter nr. %d of the method", 1 + param_index); |
243 reason.print("<parameter%d>", 1 + param_index); |
244 } else { |
244 } else { |
245 // This is the best we can do. |
245 // This is the best we can do. |
246 reason.print("loaded from a local variable at slot %d", slot); |
246 reason.print("<local%d>", slot); |
247 } |
247 } |
248 } |
248 } |
249 |
249 |
250 return TrackingStackSource(TrackingStackSource::LOCAL_VAR, bci, reason.as_string()); |
250 return TrackingStackSource(TrackingStackSource::LOCAL_VAR, bci, reason.as_string()); |
251 } |
251 } |
252 |
252 |
253 static TrackingStackSource createMethodSource(int bci, Method* method, int cp_index) { |
253 |
254 // We assume outermost caller has ResourceMark. |
254 static TrackingStackSource createConstantSource(int bci, const char *text) { |
255 stringStream reason; |
255 return TrackingStackSource(TrackingStackSource::CONSTANT, bci, text); |
256 reason.print("returned from '%s'", MethodBytecodePrinter::get_method_name(method, cp_index)); |
|
257 return TrackingStackSource(TrackingStackSource::METHOD, bci, reason.as_string()); |
|
258 } |
|
259 |
|
260 static TrackingStackSource createConstantSource(int bci) { |
|
261 return TrackingStackSource(TrackingStackSource::CONSTANT, bci, "loaded from a constant"); |
|
262 } |
256 } |
263 |
257 |
264 static TrackingStackSource createArraySource(int bci, TrackingStackSource const& array_source, |
258 static TrackingStackSource createArraySource(int bci, TrackingStackSource const& array_source, |
265 TrackingStackSource const& index_source) { |
259 TrackingStackSource const& index_source) { |
266 // We assume outermost caller has ResourceMark. |
260 // We assume outermost caller has ResourceMark. |
267 stringStream reason; |
261 stringStream reason; |
268 |
262 |
269 if (array_source.get_type() != TrackingStackSource::INVALID) { |
263 if (array_source.get_type() != TrackingStackSource::INVALID) { |
270 if (index_source.get_type() != TrackingStackSource::INVALID) { |
264 reason.print("%s", array_source.as_string()); |
271 reason.print("loaded from an array (which itself was %s) with an index %s", |
|
272 array_source.as_string(), index_source.as_string()); |
|
273 } else { |
|
274 reason.print("loaded from an array (which itself was %s)", array_source.as_string()); |
|
275 } |
|
276 } else { |
265 } else { |
277 if (index_source.get_type() != TrackingStackSource::INVALID) { |
266 reason.print("array"); |
278 reason.print("loaded from an array with an index %s", index_source.as_string()); |
267 } |
279 } else { |
268 if (index_source.get_type() != TrackingStackSource::INVALID) { |
280 reason.print("loaded from an array"); |
269 reason.print("[%s]", index_source.as_string()); |
281 } |
270 } else { |
|
271 reason.print("[...]"); |
282 } |
272 } |
283 |
273 |
284 return TrackingStackSource(TrackingStackSource::ARRAY_ELEM, bci, reason.as_string()); |
274 return TrackingStackSource(TrackingStackSource::ARRAY_ELEM, bci, reason.as_string()); |
285 } |
275 } |
286 |
276 |
287 static TrackingStackSource createFieldSource(int bci, Method* method, int cp_index, |
277 static TrackingStackSource createFieldSource(int bci, Method* method, int cp_index, |
288 TrackingStackSource const& object_source) { |
278 TrackingStackSource const& object_source) { |
289 // We assume outermost caller has ResourceMark. |
279 // We assume outermost caller has ResourceMark. |
290 stringStream reason; |
280 stringStream reason; |
291 |
281 |
|
282 // GLGL We could also print the type of the field. Should we do that? |
|
283 //MethodBytecodePrinter::get_klass_name(method, cp_index) |
292 if (object_source.get_type() != TrackingStackSource::INVALID) { |
284 if (object_source.get_type() != TrackingStackSource::INVALID) { |
293 reason.print("loaded from field '%s' of an object %s", |
285 reason.print("%s.", object_source.as_string()); |
294 MethodBytecodePrinter::get_field_and_class(method, cp_index), |
286 } |
295 object_source.as_string()); |
287 reason.print("%s", MethodBytecodePrinter::get_field_name(method, cp_index)); |
296 } else { |
|
297 reason.print("loaded from field '%s' of an object", |
|
298 MethodBytecodePrinter::get_field_and_class(method, cp_index)); |
|
299 } |
|
300 |
288 |
301 return TrackingStackSource(TrackingStackSource::FIELD_ELEM, bci, reason.as_string()); |
289 return TrackingStackSource(TrackingStackSource::FIELD_ELEM, bci, reason.as_string()); |
302 } |
290 } |
303 |
291 |
304 static TrackingStackSource createStaticFieldSource(int bci, Method* method, int cp_index) { |
292 static TrackingStackSource createStaticFieldSource(int bci, Method* method, int cp_index) { |
305 // We assume outermost caller has ResourceMark. |
293 // We assume outermost caller has ResourceMark. |
306 stringStream reason; |
294 stringStream reason; |
307 reason.print("loaded from static field '%s'", |
295 reason.print("static %s", |
308 MethodBytecodePrinter::get_field_and_class(method, cp_index)); |
296 MethodBytecodePrinter::get_field_and_class(method, cp_index)); |
309 |
297 |
310 return TrackingStackSource(TrackingStackSource::FIELD_ELEM, bci, reason.as_string()); |
298 return TrackingStackSource(TrackingStackSource::FIELD_ELEM, bci, reason.as_string()); |
311 } |
299 } |
312 |
300 |
1003 case Bytecodes::_dload_3: |
991 case Bytecodes::_dload_3: |
1004 case Bytecodes::_aload_3: |
992 case Bytecodes::_aload_3: |
1005 return createLocalVarSource(source_bci, _method, 3); |
993 return createLocalVarSource(source_bci, _method, 3); |
1006 |
994 |
1007 case Bytecodes::_aconst_null: |
995 case Bytecodes::_aconst_null: |
|
996 return createConstantSource(source_bci, "null"); |
1008 case Bytecodes::_iconst_m1: |
997 case Bytecodes::_iconst_m1: |
|
998 return createConstantSource(source_bci, "-1"); |
1009 case Bytecodes::_iconst_0: |
999 case Bytecodes::_iconst_0: |
|
1000 return createConstantSource(source_bci, "0"); |
1010 case Bytecodes::_iconst_1: |
1001 case Bytecodes::_iconst_1: |
|
1002 return createConstantSource(source_bci, "1"); |
1011 case Bytecodes::_iconst_2: |
1003 case Bytecodes::_iconst_2: |
|
1004 return createConstantSource(source_bci, "2"); |
1012 case Bytecodes::_iconst_3: |
1005 case Bytecodes::_iconst_3: |
|
1006 return createConstantSource(source_bci, "3"); |
1013 case Bytecodes::_iconst_4: |
1007 case Bytecodes::_iconst_4: |
|
1008 return createConstantSource(source_bci, "4"); |
1014 case Bytecodes::_iconst_5: |
1009 case Bytecodes::_iconst_5: |
|
1010 return createConstantSource(source_bci, "5"); |
1015 case Bytecodes::_lconst_0: |
1011 case Bytecodes::_lconst_0: |
|
1012 return createConstantSource(source_bci, "0L"); |
1016 case Bytecodes::_lconst_1: |
1013 case Bytecodes::_lconst_1: |
|
1014 return createConstantSource(source_bci, "1L"); |
1017 case Bytecodes::_fconst_0: |
1015 case Bytecodes::_fconst_0: |
|
1016 return createConstantSource(source_bci, "0.0f"); |
1018 case Bytecodes::_fconst_1: |
1017 case Bytecodes::_fconst_1: |
|
1018 return createConstantSource(source_bci, "1.0f"); |
1019 case Bytecodes::_fconst_2: |
1019 case Bytecodes::_fconst_2: |
|
1020 return createConstantSource(source_bci, "2.0f"); |
1020 case Bytecodes::_dconst_0: |
1021 case Bytecodes::_dconst_0: |
|
1022 return createConstantSource(source_bci, "0.0"); |
1021 case Bytecodes::_dconst_1: |
1023 case Bytecodes::_dconst_1: |
1022 case Bytecodes::_bipush: |
1024 return createConstantSource(source_bci, "1.0"); |
1023 case Bytecodes::_sipush: |
1025 case Bytecodes::_bipush: { |
1024 return createConstantSource(source_bci); |
1026 jbyte con = *(jbyte*) (code_base + source_bci + 1); |
1025 |
1027 stringStream ss; |
|
1028 ss.print("%d", con); |
|
1029 return createConstantSource(source_bci, ss.as_string()); |
|
1030 } |
|
1031 case Bytecodes::_sipush: { |
|
1032 u2 con = Bytes::get_Java_u2(code_base + source_bci + 1); |
|
1033 stringStream ss; |
|
1034 ss.print("%d", con); |
|
1035 return createConstantSource(source_bci, ss.as_string()); |
|
1036 } |
1026 case Bytecodes::_iaload: |
1037 case Bytecodes::_iaload: |
1027 case Bytecodes::_faload: |
1038 case Bytecodes::_faload: |
1028 case Bytecodes::_aaload: |
1039 case Bytecodes::_aaload: |
1029 case Bytecodes::_baload: |
1040 case Bytecodes::_baload: |
1030 case Bytecodes::_caload: |
1041 case Bytecodes::_caload: |
1039 case Bytecodes::_invokevirtual: |
1050 case Bytecodes::_invokevirtual: |
1040 case Bytecodes::_invokespecial: |
1051 case Bytecodes::_invokespecial: |
1041 case Bytecodes::_invokestatic: |
1052 case Bytecodes::_invokestatic: |
1042 case Bytecodes::_invokeinterface: { |
1053 case Bytecodes::_invokeinterface: { |
1043 int cp_index = Bytes::get_native_u2(code_base + pos) DEBUG_ONLY(+ ConstantPool::CPCACHE_INDEX_TAG); |
1054 int cp_index = Bytes::get_native_u2(code_base + pos) DEBUG_ONLY(+ ConstantPool::CPCACHE_INDEX_TAG); |
1044 return createMethodSource(source_bci, _method, cp_index); |
1055 // We assume outermost caller has ResourceMark. |
|
1056 stringStream reason; |
|
1057 if (max_detail == 5 /* Todo: introduce a constant ... */) { |
|
1058 reason.print("The return value of '%s'", MethodBytecodePrinter::get_method_name(_method, cp_index)); |
|
1059 } else { |
|
1060 reason.print("%s", MethodBytecodePrinter::get_method_name(_method, cp_index)); |
|
1061 } |
|
1062 return TrackingStackSource(TrackingStackSource::METHOD, source_bci, reason.as_string()); |
1045 } |
1063 } |
1046 |
1064 |
1047 case Bytecodes::_getstatic: |
1065 case Bytecodes::_getstatic: |
1048 return createStaticFieldSource(source_bci, _method, |
1066 return createStaticFieldSource(source_bci, _method, |
1049 Bytes::get_native_u2(code_base + pos) + ConstantPool::CPCACHE_INDEX_TAG); |
1067 Bytes::get_native_u2(code_base + pos) + ConstantPool::CPCACHE_INDEX_TAG); |
1078 int result = -1; |
1096 int result = -1; |
1079 |
1097 |
1080 switch (code) { |
1098 switch (code) { |
1081 case Bytecodes::_iaload: |
1099 case Bytecodes::_iaload: |
1082 if (reason != NULL) { |
1100 if (reason != NULL) { |
1083 *reason = "while trying to load from a null int array"; |
1101 *reason = "Can not load from null int array."; |
1084 } |
1102 } |
1085 |
1103 |
1086 result = 1; |
1104 result = 1; |
1087 break; |
1105 break; |
1088 |
1106 |
1089 case Bytecodes::_faload: |
1107 case Bytecodes::_faload: |
1090 if (reason != NULL) { |
1108 if (reason != NULL) { |
1091 *reason = "while trying to load from a null float array"; |
1109 *reason = "Can not load from null float array."; |
1092 } |
1110 } |
1093 |
1111 |
1094 result = 1; |
1112 result = 1; |
1095 break; |
1113 break; |
1096 |
1114 |
1097 case Bytecodes::_aaload: |
1115 case Bytecodes::_aaload: |
1098 if (reason != NULL) { |
1116 if (reason != NULL) { |
1099 *reason = "while trying to load from a null object array"; |
1117 *reason = "Can not load from null object array."; |
1100 } |
1118 } |
1101 |
1119 |
1102 result = 1; |
1120 result = 1; |
1103 break; |
1121 break; |
1104 |
1122 |
1105 case Bytecodes::_baload: |
1123 case Bytecodes::_baload: |
1106 if (reason != NULL) { |
1124 if (reason != NULL) { |
1107 *reason = "while trying to load from a null byte (or boolean) array"; |
1125 *reason = "Can not load from null byte/boolean array."; |
1108 } |
1126 } |
1109 |
1127 |
1110 result = 1; |
1128 result = 1; |
1111 break; |
1129 break; |
1112 |
1130 |
1113 case Bytecodes::_caload: |
1131 case Bytecodes::_caload: |
1114 if (reason != NULL) { |
1132 if (reason != NULL) { |
1115 *reason = "while trying to load from a null char array"; |
1133 *reason = "Can not load from null char array."; |
1116 } |
1134 } |
1117 |
1135 |
1118 result = 1; |
1136 result = 1; |
1119 break; |
1137 break; |
1120 |
1138 |
1121 case Bytecodes::_saload: |
1139 case Bytecodes::_saload: |
1122 if (reason != NULL) { |
1140 if (reason != NULL) { |
1123 *reason = "while trying to load from a null short array"; |
1141 *reason = "Can not load from null short array."; |
1124 } |
1142 } |
1125 |
1143 |
1126 result = 1; |
1144 result = 1; |
1127 break; |
1145 break; |
1128 |
1146 |
1129 case Bytecodes::_laload: |
1147 case Bytecodes::_laload: |
1130 if (reason != NULL) { |
1148 if (reason != NULL) { |
1131 *reason = "while trying to load from a null long array"; |
1149 *reason = "Can not load from null long array."; |
1132 } |
1150 } |
1133 |
1151 |
1134 result = 1; |
1152 result = 1; |
1135 break; |
1153 break; |
1136 |
1154 |
1137 case Bytecodes::_daload: |
1155 case Bytecodes::_daload: |
1138 if (reason != NULL) { |
1156 if (reason != NULL) { |
1139 *reason = "while trying to load from a null double array"; |
1157 *reason = "Can not load from null double array."; |
1140 } |
1158 } |
1141 |
1159 |
1142 result = 1; |
1160 result = 1; |
1143 break; |
1161 break; |
1144 |
1162 |
1145 case Bytecodes::_iastore: |
1163 case Bytecodes::_iastore: |
1146 if (reason != NULL) { |
1164 if (reason != NULL) { |
1147 *reason = "while trying to store to a null int array"; |
1165 *reason = "Can not store to null int array."; |
1148 } |
1166 } |
1149 |
1167 |
1150 result = 2; |
1168 result = 2; |
1151 break; |
1169 break; |
1152 |
1170 |
1153 case Bytecodes::_lastore: |
1171 case Bytecodes::_lastore: |
1154 if (reason != NULL) { |
1172 if (reason != NULL) { |
1155 *reason = "while trying to store to a null long array"; |
1173 *reason = "Can not store to null long array."; |
1156 } |
1174 } |
1157 |
1175 |
1158 result = 3; |
1176 result = 3; |
1159 break; |
1177 break; |
1160 |
1178 |
1161 case Bytecodes::_fastore: |
1179 case Bytecodes::_fastore: |
1162 if (reason != NULL) { |
1180 if (reason != NULL) { |
1163 *reason = "while trying to store to a null float array"; |
1181 *reason = "Can not store to null float array."; |
1164 } |
1182 } |
1165 |
1183 |
1166 result = 2; |
1184 result = 2; |
1167 break; |
1185 break; |
1168 |
1186 |
1169 case Bytecodes::_dastore: |
1187 case Bytecodes::_dastore: |
1170 if (reason != NULL) { |
1188 if (reason != NULL) { |
1171 *reason = "while trying to store to a null double array"; |
1189 *reason = "Can not store to null double array."; |
1172 } |
1190 } |
1173 |
1191 |
1174 result = 3; |
1192 result = 3; |
1175 break; |
1193 break; |
1176 |
1194 |
1177 case Bytecodes::_aastore: |
1195 case Bytecodes::_aastore: |
1178 if (reason != NULL) { |
1196 if (reason != NULL) { |
1179 *reason = "while trying to store to a null object array"; |
1197 *reason = "Can not store to null object array."; |
1180 } |
1198 } |
1181 |
1199 |
1182 result = 2; |
1200 result = 2; |
1183 break; |
1201 break; |
1184 |
1202 |
1185 case Bytecodes::_bastore: |
1203 case Bytecodes::_bastore: |
1186 if (reason != NULL) { |
1204 if (reason != NULL) { |
1187 *reason = "while trying to store to a null byte (or boolean) array"; |
1205 *reason = "Can not store to to null byte/boolean array."; |
1188 } |
1206 } |
1189 |
1207 |
1190 result = 2; |
1208 result = 2; |
1191 break; |
1209 break; |
1192 |
1210 |
1193 case Bytecodes::_castore: |
1211 case Bytecodes::_castore: |
1194 if (reason != NULL) { |
1212 if (reason != NULL) { |
1195 *reason = "while trying to store to a null char array"; |
1213 *reason = "Can not store to to null char array."; |
1196 } |
1214 } |
1197 |
1215 |
1198 result = 2; |
1216 result = 2; |
1199 break; |
1217 break; |
1200 |
1218 |
1201 case Bytecodes::_sastore: |
1219 case Bytecodes::_sastore: |
1202 if (reason != NULL) { |
1220 if (reason != NULL) { |
1203 *reason = "while trying to store to a null short array"; |
1221 *reason = "Can not store to null short array."; |
1204 } |
1222 } |
1205 |
1223 |
1206 result = 2; |
1224 result = 2; |
1207 break; |
1225 break; |
1208 |
1226 |
1213 ConstantPool* cp = _method->constants(); |
1231 ConstantPool* cp = _method->constants(); |
1214 int name_and_type_index = cp->name_and_type_ref_index_at(cp_index); |
1232 int name_and_type_index = cp->name_and_type_ref_index_at(cp_index); |
1215 int name_index = cp->name_ref_index_at(name_and_type_index); |
1233 int name_index = cp->name_ref_index_at(name_and_type_index); |
1216 Symbol* name = cp->symbol_at(name_index); |
1234 Symbol* name = cp->symbol_at(name_index); |
1217 stringStream ss; |
1235 stringStream ss; |
1218 ss.print("while trying to read the field '%s' of a null object", name->as_C_string()); |
1236 ss.print("Can not read field '%s'.", name->as_C_string()); |
1219 *reason = ss.as_string(); |
1237 *reason = ss.as_string(); |
1220 } |
1238 } |
1221 |
1239 |
1222 result = 0; |
1240 result = 0; |
1223 } |
1241 } |
1224 |
1242 |
1225 break; |
1243 break; |
1226 |
1244 |
1227 case Bytecodes::_arraylength: |
1245 case Bytecodes::_arraylength: |
1228 if (reason != NULL) { |
1246 if (reason != NULL) { |
1229 *reason = "while trying to get the length of a null array"; |
1247 *reason = "Can not read the array length."; |
1230 } |
1248 } |
1231 |
1249 |
1232 result = 0; |
1250 result = 0; |
1233 break; |
1251 break; |
1234 |
1252 |
1235 case Bytecodes::_athrow: |
1253 case Bytecodes::_athrow: |
1236 if (reason != NULL) { |
1254 if (reason != NULL) { |
1237 *reason = "while trying to throw a null exception object"; |
1255 *reason = "Can not throw a null exception object."; |
1238 } |
1256 } |
1239 |
1257 |
1240 result = 0; |
1258 result = 0; |
1241 break; |
1259 break; |
1242 |
1260 |
1243 case Bytecodes::_monitorenter: |
1261 case Bytecodes::_monitorenter: |
1244 if (reason != NULL) { |
1262 if (reason != NULL) { |
1245 *reason = "while trying to enter a null monitor"; |
1263 *reason = "Can not enter a null monitor."; |
1246 } |
1264 } |
1247 |
1265 |
1248 result = 0; |
1266 result = 0; |
1249 break; |
1267 break; |
1250 |
1268 |
1251 case Bytecodes::_monitorexit: |
1269 case Bytecodes::_monitorexit: |
1252 if (reason != NULL) { |
1270 if (reason != NULL) { |
1253 *reason = "while trying to exit a null monitor"; |
1271 *reason = "Can not exit a null monitor."; |
1254 } |
1272 } |
1255 |
1273 |
1256 result = 0; |
1274 result = 0; |
1257 break; |
1275 break; |
1258 |
1276 |