bytecodeStream.hpp 8.5 KB
Newer Older
D
duke 已提交
1
/*
J
Merge  
jrose 已提交
2
 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
19 20 21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
22 23 24
 *
 */

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
#ifndef SHARE_VM_INTERPRETER_BYTECODESTREAM_HPP
#define SHARE_VM_INTERPRETER_BYTECODESTREAM_HPP

#include "interpreter/bytecode.hpp"
#include "memory/allocation.hpp"
#include "oops/methodOop.hpp"
#ifdef TARGET_ARCH_x86
# include "bytes_x86.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "bytes_sparc.hpp"
#endif
#ifdef TARGET_ARCH_zero
# include "bytes_zero.hpp"
#endif

D
duke 已提交
41 42 43 44 45 46 47 48 49 50
// A BytecodeStream is used for fast iteration over the bytecodes
// of a methodOop.
//
// Usage:
//
// BytecodeStream s(method);
// Bytecodes::Code c;
// while ((c = s.next()) >= 0) {
//   ...
// }
51

D
duke 已提交
52 53
// A RawBytecodeStream is a simple version of BytecodeStream.
// It is used ONLY when we know the bytecodes haven't been rewritten
54
// yet, such as in the rewriter or the verifier.
D
duke 已提交
55

56 57
// Here is the common base class for both RawBytecodeStream and BytecodeStream:
class BaseBytecodeStream: StackObj {
D
duke 已提交
58 59 60 61 62 63 64 65 66 67
 protected:
  // stream buffer
  methodHandle    _method;                       // read from method directly

  // reading position
  int             _bci;                          // bci if current bytecode
  int             _next_bci;                     // bci of next bytecode
  int             _end_bci;                      // bci after the current iteration interval

  // last bytecode read
68
  Bytecodes::Code _raw_code;
D
duke 已提交
69
  bool            _is_wide;
70
  bool            _is_raw;                       // false in 'cooked' BytecodeStream
D
duke 已提交
71 72

  // Construction
73
  BaseBytecodeStream(methodHandle method) : _method(method) {
D
duke 已提交
74
    set_interval(0, _method->code_size());
75
    _is_raw = false;
D
duke 已提交
76 77
  }

78
 public:
D
duke 已提交
79 80 81 82 83 84 85 86 87 88 89 90 91 92
  // Iteration control
  void set_interval(int beg_bci, int end_bci) {
    // iterate over the interval [beg_bci, end_bci)
    assert(0 <= beg_bci && beg_bci <= method()->code_size(), "illegal beg_bci");
    assert(0 <= end_bci && end_bci <= method()->code_size(), "illegal end_bci");
    // setup of iteration pointers
    _bci      = beg_bci;
    _next_bci = beg_bci;
    _end_bci  = end_bci;
  }
  void set_start   (int beg_bci) {
    set_interval(beg_bci, _method->code_size());
  }

93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
  bool is_raw() const { return _is_raw; }

  // Stream attributes
  methodHandle    method() const                 { return _method; }

  int             bci() const                    { return _bci; }
  int             next_bci() const               { return _next_bci; }
  int             end_bci() const                { return _end_bci; }

  Bytecodes::Code raw_code() const               { return _raw_code; }
  bool            is_wide() const                { return _is_wide; }
  int             instruction_size() const       { return (_next_bci - _bci); }
  bool            is_last_bytecode() const       { return _next_bci >= _end_bci; }

  address         bcp() const                    { return method()->code_base() + _bci; }
  Bytecode*       bytecode() const               { return Bytecode_at(bcp()); }

  // State changes
  void            set_next_bci(int bci)          { assert(0 <= bci && bci <= method()->code_size(), "illegal bci"); _next_bci = bci; }

  // Bytecode-specific attributes
  int             dest() const                   { return bci() + bytecode()->get_offset_s2(raw_code()); }
  int             dest_w() const                 { return bci() + bytecode()->get_offset_s4(raw_code()); }

  // One-byte indices.
  int             get_index_u1() const           { assert_raw_index_size(1); return *(jubyte*)(bcp()+1); }

 protected:
  void assert_raw_index_size(int size) const NOT_DEBUG_RETURN;
  void assert_raw_stream(bool want_raw) const NOT_DEBUG_RETURN;
};

class RawBytecodeStream: public BaseBytecodeStream {
 public:
  // Construction
  RawBytecodeStream(methodHandle method) : BaseBytecodeStream(method) {
    _is_raw = true;
  }

 public:
D
duke 已提交
133 134 135 136 137 138 139 140
  // Iteration
  // Use raw_next() rather than next() for faster method reference
  Bytecodes::Code raw_next() {
    Bytecodes::Code code;
    // set reading position
    _bci = _next_bci;
    assert(!is_last_bytecode(), "caller should check is_last_bytecode()");

141
    address bcp = this->bcp();
D
duke 已提交
142 143 144 145 146 147 148 149 150
    code        = Bytecodes::code_or_bp_at(bcp);

    // set next bytecode position
    int l = Bytecodes::length_for(code);
    if (l > 0 && (_bci + l) <= _end_bci) {
      assert(code != Bytecodes::_wide && code != Bytecodes::_tableswitch
             && code != Bytecodes::_lookupswitch, "can't be special bytecode");
      _is_wide = false;
      _next_bci += l;
151
      _raw_code = code;
D
duke 已提交
152 153 154 155 156 157 158
      return code;
    } else {
      return raw_next_special(code);
    }
  }
  Bytecodes::Code raw_next_special(Bytecodes::Code code);

159 160 161 162
  // Unsigned indices, widening, with no swapping of bytes
  int             get_index() const          { return (is_wide()) ? get_index_u2_raw(bcp() + 2) : get_index_u1(); }
  // Get an unsigned 2-byte index, with no swapping of bytes.
  int             get_index_u2() const       { assert(!is_wide(), ""); return get_index_u2_raw(bcp() + 1);  }
163 164

 private:
165 166 167
  int get_index_u2_raw(address p) const {
    assert_raw_index_size(2); assert_raw_stream(true);
    return Bytes::get_Java_u2(p);
168
  }
D
duke 已提交
169 170 171 172 173
};

// In BytecodeStream, non-java bytecodes will be translated into the
// corresponding java bytecodes.

174 175 176
class BytecodeStream: public BaseBytecodeStream {
  Bytecodes::Code _code;

D
duke 已提交
177 178
 public:
  // Construction
179
  BytecodeStream(methodHandle method) : BaseBytecodeStream(method) { }
D
duke 已提交
180 181 182

  // Iteration
  Bytecodes::Code next() {
183
    Bytecodes::Code raw_code, code;
D
duke 已提交
184 185 186 187
    // set reading position
    _bci = _next_bci;
    if (is_last_bytecode()) {
      // indicate end of bytecode stream
188
      raw_code = code = Bytecodes::_illegal;
D
duke 已提交
189 190
    } else {
      // get bytecode
191 192 193
      address bcp = this->bcp();
      raw_code = Bytecodes::code_at(bcp);
      code = Bytecodes::java_code(raw_code);
D
duke 已提交
194 195 196 197 198 199 200 201 202 203 204 205 206
      // set next bytecode position
      //
      // note that we cannot advance before having the
      // tty bytecode otherwise the stepping is wrong!
      // (carefull: length_for(...) must be used first!)
      int l = Bytecodes::length_for(code);
      if (l == 0) l = Bytecodes::length_at(bcp);
      _next_bci  += l;
      assert(_bci < _next_bci, "length must be > 0");
      // set attributes
      _is_wide      = false;
      // check for special (uncommon) cases
      if (code == Bytecodes::_wide) {
207 208
        raw_code = (Bytecodes::Code)bcp[1];
        code = raw_code;  // wide BCs are always Java-normal
D
duke 已提交
209 210 211 212
        _is_wide = true;
      }
      assert(Bytecodes::is_java_code(code), "sanity check");
    }
213
    _raw_code = raw_code;
D
duke 已提交
214 215 216 217 218
    _code = code;
    return _code;
  }

  bool            is_active_breakpoint() const   { return Bytecodes::is_active_breakpoint_at(bcp()); }
219 220 221 222 223 224 225 226 227 228 229 230
  Bytecodes::Code code() const                   { return _code; }

  // Unsigned indices, widening
  int             get_index() const              { return is_wide() ? bytecode()->get_index_u2(raw_code(), true) : get_index_u1(); }
  // Get an unsigned 2-byte index, swapping the bytes if necessary.
  int             get_index_u2() const           { assert_raw_stream(false);
                                                   return bytecode()->get_index_u2(raw_code(), false); }
  // Get an unsigned 2-byte index in native order.
  int             get_index_u2_cpcache() const   { assert_raw_stream(false);
                                                   return bytecode()->get_index_u2_cpcache(raw_code()); }
  int             get_index_u4() const           { assert_raw_stream(false);
                                                   return bytecode()->get_index_u4(raw_code()); }
231
  bool            has_index_u4() const           { return bytecode()->has_index_u4(raw_code()); }
D
duke 已提交
232
};
233 234

#endif // SHARE_VM_INTERPRETER_BYTECODESTREAM_HPP