src/hotspot/share/interpreter/bytecodeUtils.hpp
branchJEP-8220715-NPE_messages
changeset 57319 aa400d41ebd6
parent 57271 1735d39dbff9
equal deleted inserted replaced
57318:cb67307942f3 57319:aa400d41ebd6
    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