1 /*
   2  * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   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
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #ifndef SHARE_VM_INTERPRETER_BYTECODESTREAM_HPP
  26 #define SHARE_VM_INTERPRETER_BYTECODESTREAM_HPP
  27 
  28 #include "interpreter/bytecode.hpp"
  29 #include "memory/allocation.hpp"
  30 #include "oops/methodOop.hpp"
  31 #ifdef TARGET_ARCH_x86
  32 # include "bytes_x86.hpp"
  33 #endif
  34 #ifdef TARGET_ARCH_sparc
  35 # include "bytes_sparc.hpp"
  36 #endif
  37 #ifdef TARGET_ARCH_zero
  38 # include "bytes_zero.hpp"
  39 #endif
  40 
  41 // A BytecodeStream is used for fast iteration over the bytecodes
  42 // of a methodOop.
  43 //
  44 // Usage:
  45 //
  46 // BytecodeStream s(method);
  47 // Bytecodes::Code c;
  48 // while ((c = s.next()) >= 0) {
  49 //   ...
  50 // }
  51 
  52 // A RawBytecodeStream is a simple version of BytecodeStream.
  53 // It is used ONLY when we know the bytecodes haven't been rewritten
  54 // yet, such as in the rewriter or the verifier.
  55 
  56 // Here is the common base class for both RawBytecodeStream and BytecodeStream:
  57 class BaseBytecodeStream: StackObj {
  58  protected:
  59   // stream buffer
  60   methodHandle    _method;                       // read from method directly
  61 
  62   // reading position
  63   int             _bci;                          // bci if current bytecode
  64   int             _next_bci;                     // bci of next bytecode
  65   int             _end_bci;                      // bci after the current iteration interval
  66 
  67   // last bytecode read
  68   Bytecodes::Code _raw_code;
  69   bool            _is_wide;
  70   bool            _is_raw;                       // false in 'cooked' BytecodeStream
  71 
  72   // Construction
  73   BaseBytecodeStream(methodHandle method) : _method(method) {
  74     set_interval(0, _method->code_size());
  75     _is_raw = false;
  76   }
  77 
  78  public:
  79   // Iteration control
  80   void set_interval(int beg_bci, int end_bci) {
  81     // iterate over the interval [beg_bci, end_bci)
  82     assert(0 <= beg_bci && beg_bci <= method()->code_size(), "illegal beg_bci");
  83     assert(0 <= end_bci && end_bci <= method()->code_size(), "illegal end_bci");
  84     // setup of iteration pointers
  85     _bci      = beg_bci;
  86     _next_bci = beg_bci;
  87     _end_bci  = end_bci;
  88   }
  89   void set_start   (int beg_bci) {
  90     set_interval(beg_bci, _method->code_size());
  91   }
  92 
  93   bool is_raw() const { return _is_raw; }
  94 
  95   // Stream attributes
  96   methodHandle    method() const                 { return _method; }
  97 
  98   int             bci() const                    { return _bci; }
  99   int             next_bci() const               { return _next_bci; }
 100   int             end_bci() const                { return _end_bci; }
 101 
 102   Bytecodes::Code raw_code() const               { return _raw_code; }
 103   bool            is_wide() const                { return _is_wide; }
 104   int             instruction_size() const       { return (_next_bci - _bci); }
 105   bool            is_last_bytecode() const       { return _next_bci >= _end_bci; }
 106 
 107   address         bcp() const                    { return method()->code_base() + _bci; }
 108   Bytecode*       bytecode() const               { return Bytecode_at(bcp()); }
 109 
 110   // State changes
 111   void            set_next_bci(int bci)          { assert(0 <= bci && bci <= method()->code_size(), "illegal bci"); _next_bci = bci; }
 112 
 113   // Bytecode-specific attributes
 114   int             dest() const                   { return bci() + bytecode()->get_offset_s2(raw_code()); }
 115   int             dest_w() const                 { return bci() + bytecode()->get_offset_s4(raw_code()); }
 116 
 117   // One-byte indices.
 118   int             get_index_u1() const           { assert_raw_index_size(1); return *(jubyte*)(bcp()+1); }
 119 
 120  protected:
 121   void assert_raw_index_size(int size) const NOT_DEBUG_RETURN;
 122   void assert_raw_stream(bool want_raw) const NOT_DEBUG_RETURN;
 123 };
 124 
 125 class RawBytecodeStream: public BaseBytecodeStream {
 126  public:
 127   // Construction
 128   RawBytecodeStream(methodHandle method) : BaseBytecodeStream(method) {
 129     _is_raw = true;
 130   }
 131 
 132  public:
 133   // Iteration
 134   // Use raw_next() rather than next() for faster method reference
 135   Bytecodes::Code raw_next() {
 136     Bytecodes::Code code;
 137     // set reading position
 138     _bci = _next_bci;
 139     assert(!is_last_bytecode(), "caller should check is_last_bytecode()");
 140 
 141     address bcp = this->bcp();
 142     code        = Bytecodes::code_or_bp_at(bcp);
 143 
 144     // set next bytecode position
 145     int l = Bytecodes::length_for(code);
 146     if (l > 0 && (_bci + l) <= _end_bci) {
 147       assert(code != Bytecodes::_wide && code != Bytecodes::_tableswitch
 148              && code != Bytecodes::_lookupswitch, "can't be special bytecode");
 149       _is_wide = false;
 150       _next_bci += l;
 151       _raw_code = code;
 152       return code;
 153     } else {
 154       return raw_next_special(code);
 155     }
 156   }
 157   Bytecodes::Code raw_next_special(Bytecodes::Code code);
 158 
 159   // Unsigned indices, widening, with no swapping of bytes
 160   int             get_index() const          { return (is_wide()) ? get_index_u2_raw(bcp() + 2) : get_index_u1(); }
 161   // Get an unsigned 2-byte index, with no swapping of bytes.
 162   int             get_index_u2() const       { assert(!is_wide(), ""); return get_index_u2_raw(bcp() + 1);  }
 163 
 164  private:
 165   int get_index_u2_raw(address p) const {
 166     assert_raw_index_size(2); assert_raw_stream(true);
 167     return Bytes::get_Java_u2(p);
 168   }
 169 };
 170 
 171 // In BytecodeStream, non-java bytecodes will be translated into the
 172 // corresponding java bytecodes.
 173 
 174 class BytecodeStream: public BaseBytecodeStream {
 175   Bytecodes::Code _code;
 176 
 177  public:
 178   // Construction
 179   BytecodeStream(methodHandle method) : BaseBytecodeStream(method) { }
 180 
 181   // Iteration
 182   Bytecodes::Code next() {
 183     Bytecodes::Code raw_code, code;
 184     // set reading position
 185     _bci = _next_bci;
 186     if (is_last_bytecode()) {
 187       // indicate end of bytecode stream
 188       raw_code = code = Bytecodes::_illegal;
 189     } else {
 190       // get bytecode
 191       address bcp = this->bcp();
 192       raw_code = Bytecodes::code_at(bcp);
 193       code = Bytecodes::java_code(raw_code);
 194       // set next bytecode position
 195       //
 196       // note that we cannot advance before having the
 197       // tty bytecode otherwise the stepping is wrong!
 198       // (carefull: length_for(...) must be used first!)
 199       int l = Bytecodes::length_for(code);
 200       if (l == 0) l = Bytecodes::length_at(bcp);
 201       _next_bci  += l;
 202       assert(_bci < _next_bci, "length must be > 0");
 203       // set attributes
 204       _is_wide      = false;
 205       // check for special (uncommon) cases
 206       if (code == Bytecodes::_wide) {
 207         raw_code = (Bytecodes::Code)bcp[1];
 208         code = raw_code;  // wide BCs are always Java-normal
 209         _is_wide = true;
 210       }
 211       assert(Bytecodes::is_java_code(code), "sanity check");
 212     }
 213     _raw_code = raw_code;
 214     _code = code;
 215     return _code;
 216   }
 217 
 218   bool            is_active_breakpoint() const   { return Bytecodes::is_active_breakpoint_at(bcp()); }
 219   Bytecodes::Code code() const                   { return _code; }
 220 
 221   // Unsigned indices, widening
 222   int             get_index() const              { return is_wide() ? bytecode()->get_index_u2(raw_code(), true) : get_index_u1(); }
 223   // Get an unsigned 2-byte index, swapping the bytes if necessary.
 224   int             get_index_u2() const           { assert_raw_stream(false);
 225                                                    return bytecode()->get_index_u2(raw_code(), false); }
 226   // Get an unsigned 2-byte index in native order.
 227   int             get_index_u2_cpcache() const   { assert_raw_stream(false);
 228                                                    return bytecode()->get_index_u2_cpcache(raw_code()); }
 229   int             get_index_u4() const           { assert_raw_stream(false);
 230                                                    return bytecode()->get_index_u4(raw_code()); }
 231   bool            has_index_u4() const           { return bytecode()->has_index_u4(raw_code()); }
 232 };
 233 
 234 #endif // SHARE_VM_INTERPRETER_BYTECODESTREAM_HPP