21 * or visit www.oracle.com if you need additional information or have any |
21 * or visit www.oracle.com if you need additional information or have any |
22 * questions. |
22 * questions. |
23 * |
23 * |
24 */ |
24 */ |
25 |
25 |
26 #ifndef SHARE_CLASSFILE_BYTECODEUTILS_HPP |
26 #ifndef SHARE_INTERPRETER_BYTECODEUTILS_HPP |
27 #define SHARE_CLASSFILE_BYTECODEUTILS_HPP |
27 #define SHARE_INTERPRETER_BYTECODEUTILS_HPP |
28 |
28 |
29 #include "memory/allocation.hpp" |
29 #include "memory/allocation.hpp" |
30 #include "oops/method.hpp" |
30 #include "oops/method.hpp" |
31 #include "utilities/growableArray.hpp" |
31 #include "utilities/growableArray.hpp" |
32 |
32 #include "utilities/globalDefinitions.hpp" |
33 |
|
34 // A class which can be used to print out the bytecode |
|
35 // of a method. |
|
36 // NOTE: The method must already be rewritten. |
|
37 class MethodBytecodePrinter : public AllStatic { |
|
38 public: |
|
39 |
|
40 // Returns the external (using '.') name of the class at the given cp index in an |
|
41 // area allocated string. |
|
42 static char const* get_klass_name(Method* method, int cp_index); |
|
43 |
|
44 // Returns the name of the method(including signature, but without |
|
45 // the return type) at the given cp index in a resource area |
|
46 // allocated string. |
|
47 static char const* get_method_name(Method* method, int cp_index); |
|
48 |
|
49 // Returns the name of the field at the given cp index in |
|
50 // a resource area allocated string. |
|
51 static char const *get_field_name(Method* method, int cp_index); |
|
52 |
|
53 // Returns the name and class of the field at the given cp index in |
|
54 // a resource area allocated string. |
|
55 static char const* get_field_and_class(Method* method, int cp_index); |
|
56 }; |
|
57 |
33 |
58 class TrackingStack; |
34 class TrackingStack; |
59 class TrackingStackCreator; |
35 class TrackingStackCreator; |
60 |
36 |
61 // The entry of TrackingStack. |
37 // The entry of TrackingStack. |
138 |
114 |
139 // Returns the entry with the given index. Top of stack is at index 0. |
115 // Returns the entry with the given index. Top of stack is at index 0. |
140 TrackingStackEntry get_entry(int slot); |
116 TrackingStackEntry get_entry(int slot); |
141 }; |
117 }; |
142 |
118 |
143 // Defines a source of a slot of the operand stack. |
|
144 class TrackingStackSource { |
|
145 |
|
146 public: |
|
147 |
|
148 enum Type { |
|
149 // If the value was loaded from a local variable. |
|
150 LOCAL_VAR, |
|
151 |
|
152 // If the value was returned from a method. |
|
153 METHOD, |
|
154 |
|
155 // If the value was loaded from an array. |
|
156 ARRAY_ELEM, |
|
157 |
|
158 // If the value was loaded from a field. |
|
159 FIELD_ELEM, |
|
160 |
|
161 // If the value was from a constant. |
|
162 CONSTANT, |
|
163 |
|
164 // If the source is invalid. |
|
165 INVALID |
|
166 }; |
|
167 |
|
168 private: |
|
169 |
|
170 const char *_reason; |
|
171 |
|
172 Type _type; |
|
173 int _bci; |
|
174 |
|
175 public: |
|
176 |
|
177 TrackingStackSource(Type type, int bci, const char * reason) : _reason(reason), _type(type), _bci(bci) { } |
|
178 |
|
179 // Returns the type. |
|
180 Type get_type() const { |
|
181 return _type; |
|
182 } |
|
183 |
|
184 // Returns a human readable string describing the source. |
|
185 char const* as_string() const { |
|
186 return _reason; |
|
187 } |
|
188 }; |
|
189 |
|
190 // Analyses the bytecodes of a method and tries to create a tracking |
119 // Analyses the bytecodes of a method and tries to create a tracking |
191 // stack for each bci. The tracking stack holds the bci and type of |
120 // stack for each bci. The tracking stack holds the bci and type of |
192 // the objec on the stack. The bci (if valid) holds the bci of the |
121 // the object on the stack. The bci (if valid) holds the bci of the |
193 // instruction, which put the entry on the stack. |
122 // instruction, which put the entry on the stack. |
194 class TrackingStackCreator { |
123 class TrackingStackCreator { |
195 |
124 |
196 // The stacks. |
125 // The stacks. |
197 GrowableArray<TrackingStack*>* _stacks; |
126 GrowableArray<TrackingStack*>* _stacks; |
211 bool _added_one; |
140 bool _added_one; |
212 |
141 |
213 // If true, we have processed all bytecodes. |
142 // If true, we have processed all bytecodes. |
214 bool _all_processed; |
143 bool _all_processed; |
215 |
144 |
|
145 static const int _max_cause_detail; |
|
146 |
216 // Merges the stack the the given bci with the given stack. If there |
147 // Merges the stack the the given bci with the given stack. If there |
217 // is no stack at the bci, we just put the given stack there. This |
148 // is no stack at the bci, we just put the given stack there. This |
218 // method doesn't takes ownership of the stack. |
149 // method doesn't takes ownership of the stack. |
219 void merge(int bci, TrackingStack* stack); |
150 void merge(int bci, TrackingStack* stack); |
220 |
151 |
221 // Processes the instruction at the given bci in the method. Returns |
152 // Processes the instruction at the given bci in the method. Returns |
222 // the size of the instruction. |
153 // the size of the instruction. |
223 int do_instruction(int bci); |
154 int do_instruction(int bci); |
|
155 |
|
156 bool print_NPE_cause0(outputStream *os, int bci, int slot, int max_detail, const char *prefix = NULL); |
224 |
157 |
225 public: |
158 public: |
226 |
159 |
227 // Creates tracking stacks for the given method (the method must be |
160 // Creates tracking stacks for the given method (the method must be |
228 // rewritten already). Note that you're not allowed to use this object |
161 // rewritten already). Note that you're not allowed to use this object |
234 ~TrackingStackCreator(); |
167 ~TrackingStackCreator(); |
235 |
168 |
236 // Returns the number of stacks (this is the size of the method). |
169 // Returns the number of stacks (this is the size of the method). |
237 int get_size() { return _stacks->length() - 1; } |
170 int get_size() { return _stacks->length() - 1; } |
238 |
171 |
239 // Returns the source of the value in the given slot at the given bci. |
|
240 // The TOS has the slot number 0, that below 1 and so on. You have to |
|
241 // delete the returned object via 'delete'. 'max_detail' is the number |
|
242 // of levels for which we include sources recursively (e.g. for a source |
|
243 // which was from an array and the array was loaded from field of an |
|
244 // object which ...). The larger the value, the more detailed the source. |
|
245 TrackingStackSource get_source(int bci, int slot, int max_detail); |
|
246 |
|
247 // Assuming that a NullPointerException was thrown at the given bci, |
172 // Assuming that a NullPointerException was thrown at the given bci, |
248 // we return the nr of the slot holding the null reference. If this |
173 // we return the nr of the slot holding the null reference. If this |
249 // NPE is created by hand, we return -2 as the slot. If there |
174 // NPE is created by hand, we return -2 as the slot. If there |
250 // cannot be a NullPointerException at the bci, -1 is returned. If |
175 // cannot be a NullPointerException at the bci, -1 is returned. |
251 // 'reason' is != NULL, a description is stored, which is allocated |
176 int get_NPE_null_slot(int bci); |
252 // statically or in the resource area. |
|
253 int get_null_pointer_slot(int bci, char const** reason); |
|
254 |
177 |
|
178 // Prints a java-like expression for the bytecode that pushed |
|
179 // the value to the given slot being live at the given bci. |
|
180 // It constructs the expression recuring backwards over the |
|
181 // bytecode. |
|
182 // The TOS has the slot number 0, that below 1 and so on. |
|
183 void print_NPE_cause(outputStream *os, int bci, int slot); |
|
184 |
|
185 // Prints a string describing the failed action. |
|
186 void print_NPE_failedAction(outputStream *os, int bci); |
255 }; |
187 }; |
256 |
188 |
257 #endif // SHARE_CLASSFILE_BYTECODEUTILS_HPP |
189 #endif // SHARE_INTERPRETER_BYTECODEUTILS_HPP |