Path: blob/master/src/hotspot/share/interpreter/bytecodeStream.hpp
40949 views
/*1* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_INTERPRETER_BYTECODESTREAM_HPP25#define SHARE_INTERPRETER_BYTECODESTREAM_HPP2627#include "interpreter/bytecode.hpp"28#include "memory/allocation.hpp"29#include "oops/method.hpp"30#include "utilities/bytes.hpp"3132// A BytecodeStream is used for fast iteration over the bytecodes33// of a Method*.34//35// Usage:36//37// BytecodeStream s(method);38// Bytecodes::Code c;39// while ((c = s.next()) >= 0) {40// ...41// }4243// A RawBytecodeStream is a simple version of BytecodeStream.44// It is used ONLY when we know the bytecodes haven't been rewritten45// yet, such as in the rewriter or the verifier.4647// Here is the common base class for both RawBytecodeStream and BytecodeStream:48class BaseBytecodeStream: StackObj {49protected:50// stream buffer51methodHandle _method; // read from method directly5253// reading position54int _bci; // bci if current bytecode55int _next_bci; // bci of next bytecode56int _end_bci; // bci after the current iteration interval5758// last bytecode read59Bytecodes::Code _raw_code;60bool _is_wide;61bool _is_raw; // false in 'cooked' BytecodeStream6263// Construction64BaseBytecodeStream(const methodHandle& method);6566public:67// Iteration control68void set_interval(int beg_bci, int end_bci) {69// iterate over the interval [beg_bci, end_bci)70assert(0 <= beg_bci && beg_bci <= method()->code_size(), "illegal beg_bci");71assert(0 <= end_bci && end_bci <= method()->code_size(), "illegal end_bci");72// setup of iteration pointers73_bci = beg_bci;74_next_bci = beg_bci;75_end_bci = end_bci;76}77void set_start (int beg_bci) {78set_interval(beg_bci, _method->code_size());79}8081bool is_raw() const { return _is_raw; }8283// Stream attributes84const methodHandle& method() const { return _method; }8586int bci() const { return _bci; }87int next_bci() const { return _next_bci; }88int end_bci() const { return _end_bci; }8990Bytecodes::Code raw_code() const { return _raw_code; }91bool is_wide() const { return _is_wide; }92int instruction_size() const { return (_next_bci - _bci); }93bool is_last_bytecode() const { return _next_bci >= _end_bci; }9495address bcp() const { return method()->code_base() + _bci; }96Bytecode bytecode() const { return Bytecode(_method(), bcp()); }9798// State changes99void set_next_bci(int bci) { assert(0 <= bci && bci <= method()->code_size(), "illegal bci"); _next_bci = bci; }100101// Bytecode-specific attributes102int dest() const { return bci() + bytecode().get_offset_s2(raw_code()); }103int dest_w() const { return bci() + bytecode().get_offset_s4(raw_code()); }104105// One-byte indices.106int get_index_u1() const { assert_raw_index_size(1); return *(jubyte*)(bcp()+1); }107108protected:109void assert_raw_index_size(int size) const NOT_DEBUG_RETURN;110void assert_raw_stream(bool want_raw) const NOT_DEBUG_RETURN;111};112113class RawBytecodeStream: public BaseBytecodeStream {114public:115// Construction116RawBytecodeStream(const methodHandle& method) : BaseBytecodeStream(method) {117_is_raw = true;118}119120public:121// Iteration122// Use raw_next() rather than next() for faster method reference123Bytecodes::Code raw_next() {124Bytecodes::Code code;125// set reading position126_bci = _next_bci;127assert(!is_last_bytecode(), "caller should check is_last_bytecode()");128129address bcp = this->bcp();130code = Bytecodes::code_or_bp_at(bcp);131132// set next bytecode position133int len = Bytecodes::length_for(code);134if (len > 0 && (_bci <= _end_bci - len)) {135assert(code != Bytecodes::_wide && code != Bytecodes::_tableswitch136&& code != Bytecodes::_lookupswitch, "can't be special bytecode");137_is_wide = false;138_next_bci += len;139if (_next_bci <= _bci) { // Check for integer overflow140code = Bytecodes::_illegal;141}142_raw_code = code;143return code;144} else {145return raw_next_special(code);146}147}148Bytecodes::Code raw_next_special(Bytecodes::Code code);149150// Unsigned indices, widening, with no swapping of bytes151int get_index() const { return (is_wide()) ? get_index_u2_raw(bcp() + 2) : get_index_u1(); }152// Get an unsigned 2-byte index, with no swapping of bytes.153int get_index_u2() const { assert(!is_wide(), ""); return get_index_u2_raw(bcp() + 1); }154155private:156int get_index_u2_raw(address p) const {157assert_raw_index_size(2); assert_raw_stream(true);158return Bytes::get_Java_u2(p);159}160};161162// In BytecodeStream, non-java bytecodes will be translated into the163// corresponding java bytecodes.164165class BytecodeStream: public BaseBytecodeStream {166Bytecodes::Code _code;167168public:169// Construction170BytecodeStream(const methodHandle& method) : BaseBytecodeStream(method) { }171172BytecodeStream(const methodHandle& method, int bci) : BaseBytecodeStream(method) {173set_start(bci);174}175176// Iteration177Bytecodes::Code next() {178Bytecodes::Code raw_code, code;179// set reading position180_bci = _next_bci;181if (is_last_bytecode()) {182// indicate end of bytecode stream183raw_code = code = Bytecodes::_illegal;184} else {185// get bytecode186address bcp = this->bcp();187raw_code = Bytecodes::code_at(_method(), bcp);188code = Bytecodes::java_code(raw_code);189// set next bytecode position190//191// note that we cannot advance before having the192// tty bytecode otherwise the stepping is wrong!193// (carefull: length_for(...) must be used first!)194int len = Bytecodes::length_for(code);195if (len == 0) len = Bytecodes::length_at(_method(), bcp);196if (len <= 0 || (_bci > _end_bci - len) || (_bci - len >= _next_bci)) {197raw_code = code = Bytecodes::_illegal;198} else {199_next_bci += len;200assert(_bci < _next_bci, "length must be > 0");201// set attributes202_is_wide = false;203// check for special (uncommon) cases204if (code == Bytecodes::_wide) {205raw_code = (Bytecodes::Code)bcp[1];206code = raw_code; // wide BCs are always Java-normal207_is_wide = true;208}209assert(Bytecodes::is_java_code(code), "sanity check");210}211}212_raw_code = raw_code;213_code = code;214return _code;215}216217Bytecodes::Code code() const { return _code; }218219// Unsigned indices, widening220int get_index() const { return is_wide() ? bytecode().get_index_u2(raw_code(), true) : get_index_u1(); }221// Get an unsigned 2-byte index, swapping the bytes if necessary.222int get_index_u2() const { assert_raw_stream(false);223return bytecode().get_index_u2(raw_code(), false); }224// Get an unsigned 2-byte index in native order.225int get_index_u2_cpcache() const { assert_raw_stream(false);226return bytecode().get_index_u2_cpcache(raw_code()); }227int get_index_u4() const { assert_raw_stream(false);228return bytecode().get_index_u4(raw_code()); }229bool has_index_u4() const { return bytecode().has_index_u4(raw_code()); }230};231232#endif // SHARE_INTERPRETER_BYTECODESTREAM_HPP233234235