hotspot/src/share/vm/interpreter/bytecodeStream.hpp
changeset 5688 9052dc91ea67
parent 3261 c7d5aae8d3f7
child 5693 3015c564fcbc
equal deleted inserted replaced
5687:b862d1f189bd 5688:9052dc91ea67
     1 /*
     1 /*
     2  * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
     2  * Copyright 1997-2010 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    30 // BytecodeStream s(method);
    30 // BytecodeStream s(method);
    31 // Bytecodes::Code c;
    31 // Bytecodes::Code c;
    32 // while ((c = s.next()) >= 0) {
    32 // while ((c = s.next()) >= 0) {
    33 //   ...
    33 //   ...
    34 // }
    34 // }
    35 //
    35 
    36 // A RawBytecodeStream is a simple version of BytecodeStream.
    36 // A RawBytecodeStream is a simple version of BytecodeStream.
    37 // It is used ONLY when we know the bytecodes haven't been rewritten
    37 // It is used ONLY when we know the bytecodes haven't been rewritten
    38 // yet, such as in the rewriter or the verifier. Currently only the
    38 // yet, such as in the rewriter or the verifier.
    39 // verifier uses this class.
    39 
    40 
    40 // Here is the common base class for both RawBytecodeStream and BytecodeStream:
    41 class RawBytecodeStream: StackObj {
    41 class BaseBytecodeStream: StackObj {
    42  protected:
    42  protected:
    43   // stream buffer
    43   // stream buffer
    44   methodHandle    _method;                       // read from method directly
    44   methodHandle    _method;                       // read from method directly
    45 
    45 
    46   // reading position
    46   // reading position
    47   int             _bci;                          // bci if current bytecode
    47   int             _bci;                          // bci if current bytecode
    48   int             _next_bci;                     // bci of next bytecode
    48   int             _next_bci;                     // bci of next bytecode
    49   int             _end_bci;                      // bci after the current iteration interval
    49   int             _end_bci;                      // bci after the current iteration interval
    50 
    50 
    51   // last bytecode read
    51   // last bytecode read
    52   Bytecodes::Code _code;
    52   Bytecodes::Code _raw_code;
    53   bool            _is_wide;
    53   bool            _is_wide;
    54 
    54   bool            _is_raw;                       // false in 'cooked' BytecodeStream
    55  public:
    55 
    56   // Construction
    56   // Construction
    57   RawBytecodeStream(methodHandle method) : _method(method) {
    57   BaseBytecodeStream(methodHandle method) : _method(method) {
    58     set_interval(0, _method->code_size());
    58     set_interval(0, _method->code_size());
    59   }
    59     _is_raw = false;
    60 
    60   }
       
    61 
       
    62  public:
    61   // Iteration control
    63   // Iteration control
    62   void set_interval(int beg_bci, int end_bci) {
    64   void set_interval(int beg_bci, int end_bci) {
    63     // iterate over the interval [beg_bci, end_bci)
    65     // iterate over the interval [beg_bci, end_bci)
    64     assert(0 <= beg_bci && beg_bci <= method()->code_size(), "illegal beg_bci");
    66     assert(0 <= beg_bci && beg_bci <= method()->code_size(), "illegal beg_bci");
    65     assert(0 <= end_bci && end_bci <= method()->code_size(), "illegal end_bci");
    67     assert(0 <= end_bci && end_bci <= method()->code_size(), "illegal end_bci");
    70   }
    72   }
    71   void set_start   (int beg_bci) {
    73   void set_start   (int beg_bci) {
    72     set_interval(beg_bci, _method->code_size());
    74     set_interval(beg_bci, _method->code_size());
    73   }
    75   }
    74 
    76 
       
    77   bool is_raw() const { return _is_raw; }
       
    78 
       
    79   // Stream attributes
       
    80   methodHandle    method() const                 { return _method; }
       
    81 
       
    82   int             bci() const                    { return _bci; }
       
    83   int             next_bci() const               { return _next_bci; }
       
    84   int             end_bci() const                { return _end_bci; }
       
    85 
       
    86   Bytecodes::Code raw_code() const               { return _raw_code; }
       
    87   bool            is_wide() const                { return _is_wide; }
       
    88   int             instruction_size() const       { return (_next_bci - _bci); }
       
    89   bool            is_last_bytecode() const       { return _next_bci >= _end_bci; }
       
    90 
       
    91   address         bcp() const                    { return method()->code_base() + _bci; }
       
    92   Bytecode*       bytecode() const               { return Bytecode_at(bcp()); }
       
    93 
       
    94   // State changes
       
    95   void            set_next_bci(int bci)          { assert(0 <= bci && bci <= method()->code_size(), "illegal bci"); _next_bci = bci; }
       
    96 
       
    97   // Bytecode-specific attributes
       
    98   int             dest() const                   { return bci() + bytecode()->get_offset_s2(raw_code()); }
       
    99   int             dest_w() const                 { return bci() + bytecode()->get_offset_s4(raw_code()); }
       
   100 
       
   101   // One-byte indices.
       
   102   int             get_index_u1() const           { assert_raw_index_size(1); return *(jubyte*)(bcp()+1); }
       
   103 
       
   104  protected:
       
   105   void assert_raw_index_size(int size) const NOT_DEBUG_RETURN;
       
   106   void assert_raw_stream(bool want_raw) const NOT_DEBUG_RETURN;
       
   107 };
       
   108 
       
   109 class RawBytecodeStream: public BaseBytecodeStream {
       
   110  public:
       
   111   // Construction
       
   112   RawBytecodeStream(methodHandle method) : BaseBytecodeStream(method) {
       
   113     _is_raw = true;
       
   114   }
       
   115 
       
   116  public:
    75   // Iteration
   117   // Iteration
    76   // Use raw_next() rather than next() for faster method reference
   118   // Use raw_next() rather than next() for faster method reference
    77   Bytecodes::Code raw_next() {
   119   Bytecodes::Code raw_next() {
    78     Bytecodes::Code code;
   120     Bytecodes::Code code;
    79     // set reading position
   121     // set reading position
    80     _bci = _next_bci;
   122     _bci = _next_bci;
    81     assert(!is_last_bytecode(), "caller should check is_last_bytecode()");
   123     assert(!is_last_bytecode(), "caller should check is_last_bytecode()");
    82 
   124 
    83     address bcp = RawBytecodeStream::bcp();
   125     address bcp = this->bcp();
    84     code        = Bytecodes::code_or_bp_at(bcp);
   126     code        = Bytecodes::code_or_bp_at(bcp);
    85 
   127 
    86     // set next bytecode position
   128     // set next bytecode position
    87     int l = Bytecodes::length_for(code);
   129     int l = Bytecodes::length_for(code);
    88     if (l > 0 && (_bci + l) <= _end_bci) {
   130     if (l > 0 && (_bci + l) <= _end_bci) {
    89       assert(code != Bytecodes::_wide && code != Bytecodes::_tableswitch
   131       assert(code != Bytecodes::_wide && code != Bytecodes::_tableswitch
    90              && code != Bytecodes::_lookupswitch, "can't be special bytecode");
   132              && code != Bytecodes::_lookupswitch, "can't be special bytecode");
    91       _is_wide = false;
   133       _is_wide = false;
    92       _next_bci += l;
   134       _next_bci += l;
    93       _code = code;
   135       _raw_code = code;
    94       return code;
   136       return code;
    95     } else if (code == Bytecodes::_wide && _bci + 1 >= _end_bci) {
       
    96       return Bytecodes::_illegal;
       
    97     } else {
   137     } else {
    98       return raw_next_special(code);
   138       return raw_next_special(code);
    99     }
   139     }
   100   }
   140   }
   101   Bytecodes::Code raw_next_special(Bytecodes::Code code);
   141   Bytecodes::Code raw_next_special(Bytecodes::Code code);
   102 
   142 
   103   // Stream attributes
   143   // Unsigned indices, widening, with no swapping of bytes
   104   methodHandle    method() const                 { return _method; }
   144   int             get_index() const          { return (is_wide()) ? get_index_u2_raw(bcp() + 2) : get_index_u1(); }
   105 
   145   // Get an unsigned 2-byte index, with no swapping of bytes.
   106   int             bci() const                    { return _bci; }
   146   int             get_index_u2() const       { assert(!is_wide(), ""); return get_index_u2_raw(bcp() + 1);  }
   107   int             next_bci() const               { return _next_bci; }
       
   108   int             end_bci() const                { return _end_bci; }
       
   109 
       
   110   Bytecodes::Code code() const                   { return _code; }
       
   111   bool            is_wide() const                { return _is_wide; }
       
   112   int             instruction_size() const       { return (_next_bci - _bci); }
       
   113   bool            is_last_bytecode() const       { return _next_bci >= _end_bci; }
       
   114 
       
   115   address         bcp() const                    { return method()->code_base() + _bci; }
       
   116   address         next_bcp()                     { return method()->code_base() + _next_bci; }
       
   117 
       
   118   // State changes
       
   119   void            set_next_bci(int bci)          { assert(0 <= bci && bci <= method()->code_size(), "illegal bci"); _next_bci = bci; }
       
   120 
       
   121   // Bytecode-specific attributes
       
   122   int             dest() const                   { return bci() + (short)Bytes::get_Java_u2(bcp() + 1); }
       
   123   int             dest_w() const                 { return bci() + (int  )Bytes::get_Java_u4(bcp() + 1); }
       
   124 
       
   125   // Unsigned indices, widening
       
   126   int             get_index() const              { assert_index_size(is_wide() ? 2 : 1);
       
   127                                                    return (is_wide()) ? Bytes::get_Java_u2(bcp() + 2) : bcp()[1]; }
       
   128   int             get_index_big() const          { assert_index_size(2);
       
   129                                                    return (int)Bytes::get_Java_u2(bcp() + 1);  }
       
   130   int             get_index_int() const          { return has_giant_index() ? get_index_giant() : get_index_big(); }
       
   131   int             get_index_giant() const        { assert_index_size(4); return Bytes::get_native_u4(bcp() + 1); }
       
   132   int             has_giant_index() const        { return (code() == Bytecodes::_invokedynamic); }
       
   133 
   147 
   134  private:
   148  private:
   135   void assert_index_size(int required_size) const {
   149   int get_index_u2_raw(address p) const {
   136 #ifdef ASSERT
   150     assert_raw_index_size(2); assert_raw_stream(true);
   137     int isize = instruction_size() - (int)_is_wide - 1;
   151     return Bytes::get_Java_u2(p);
   138     if (isize == 2 && code() == Bytecodes::_iinc)
       
   139       isize = 1;
       
   140     else if (isize <= 2)
       
   141       ;                         // no change
       
   142     else if (has_giant_index())
       
   143       isize = 4;
       
   144     else
       
   145       isize = 2;
       
   146     assert(isize = required_size, "wrong index size");
       
   147 #endif
       
   148   }
   152   }
   149 };
   153 };
   150 
   154 
   151 // In BytecodeStream, non-java bytecodes will be translated into the
   155 // In BytecodeStream, non-java bytecodes will be translated into the
   152 // corresponding java bytecodes.
   156 // corresponding java bytecodes.
   153 
   157 
   154 class BytecodeStream: public RawBytecodeStream {
   158 class BytecodeStream: public BaseBytecodeStream {
       
   159   Bytecodes::Code _code;
       
   160 
   155  public:
   161  public:
   156   // Construction
   162   // Construction
   157   BytecodeStream(methodHandle method) : RawBytecodeStream(method) { }
   163   BytecodeStream(methodHandle method) : BaseBytecodeStream(method) { }
   158 
   164 
   159   // Iteration
   165   // Iteration
   160   Bytecodes::Code next() {
   166   Bytecodes::Code next() {
   161     Bytecodes::Code code;
   167     Bytecodes::Code raw_code, code;
   162     // set reading position
   168     // set reading position
   163     _bci = _next_bci;
   169     _bci = _next_bci;
   164     if (is_last_bytecode()) {
   170     if (is_last_bytecode()) {
   165       // indicate end of bytecode stream
   171       // indicate end of bytecode stream
   166       code = Bytecodes::_illegal;
   172       raw_code = code = Bytecodes::_illegal;
   167     } else {
   173     } else {
   168       // get bytecode
   174       // get bytecode
   169       address bcp = BytecodeStream::bcp();
   175       address bcp = this->bcp();
   170       code        = Bytecodes::java_code_at(bcp);
   176       raw_code = Bytecodes::code_at(bcp);
       
   177       code = Bytecodes::java_code(raw_code);
   171       // set next bytecode position
   178       // set next bytecode position
   172       //
   179       //
   173       // note that we cannot advance before having the
   180       // note that we cannot advance before having the
   174       // tty bytecode otherwise the stepping is wrong!
   181       // tty bytecode otherwise the stepping is wrong!
   175       // (carefull: length_for(...) must be used first!)
   182       // (carefull: length_for(...) must be used first!)
   179       assert(_bci < _next_bci, "length must be > 0");
   186       assert(_bci < _next_bci, "length must be > 0");
   180       // set attributes
   187       // set attributes
   181       _is_wide      = false;
   188       _is_wide      = false;
   182       // check for special (uncommon) cases
   189       // check for special (uncommon) cases
   183       if (code == Bytecodes::_wide) {
   190       if (code == Bytecodes::_wide) {
   184         code = (Bytecodes::Code)bcp[1];
   191         raw_code = (Bytecodes::Code)bcp[1];
       
   192         code = raw_code;  // wide BCs are always Java-normal
   185         _is_wide = true;
   193         _is_wide = true;
   186       }
   194       }
   187       assert(Bytecodes::is_java_code(code), "sanity check");
   195       assert(Bytecodes::is_java_code(code), "sanity check");
   188     }
   196     }
       
   197     _raw_code = raw_code;
   189     _code = code;
   198     _code = code;
   190     return _code;
   199     return _code;
   191   }
   200   }
   192 
   201 
   193   bool            is_active_breakpoint() const   { return Bytecodes::is_active_breakpoint_at(bcp()); }
   202   bool            is_active_breakpoint() const   { return Bytecodes::is_active_breakpoint_at(bcp()); }
       
   203   Bytecodes::Code code() const                   { return _code; }
       
   204 
       
   205   // Unsigned indices, widening
       
   206   int             get_index() const              { return is_wide() ? bytecode()->get_index_u2(raw_code(), true) : get_index_u1(); }
       
   207   // Get an unsigned 2-byte index, swapping the bytes if necessary.
       
   208   int             get_index_u2() const           { assert_raw_stream(false);
       
   209                                                    return bytecode()->get_index_u2(raw_code(), false); }
       
   210   // Get an unsigned 2-byte index in native order.
       
   211   int             get_index_u2_cpcache() const   { assert_raw_stream(false);
       
   212                                                    return bytecode()->get_index_u2_cpcache(raw_code()); }
       
   213   int             get_index_u4() const           { assert_raw_stream(false);
       
   214                                                    return bytecode()->get_index_u4(raw_code()); }
       
   215   int             has_index_u4() const           { return bytecode()->get_index_u4(raw_code()); }
   194 };
   216 };