1 /* 2 * Copyright (c) 2001, 2011, 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 package sun.jvm.hotspot.interpreter; 26 27 import sun.jvm.hotspot.oops.*; 28 import sun.jvm.hotspot.runtime.*; 29 import sun.jvm.hotspot.utilities.*; 30 31 public class BytecodeStream { 32 private Method _method; 33 34 // reading position 35 private int _bci; // bci if current bytecode 36 private int _next_bci; // bci of next bytecode 37 private int _end_bci; // bci after the current iteration interval 38 39 // last bytecode read 40 private int _code; 41 private boolean _is_wide; 42 43 // Construction 44 public BytecodeStream(Method method) { 45 _method = method; 46 setInterval(0, (int) method.getCodeSize()); 47 } 48 49 // Iteration control 50 public void setInterval(int beg_bci, int end_bci) { 51 if (Assert.ASSERTS_ENABLED) { 52 Assert.that(0 <= beg_bci && beg_bci <= _method.getCodeSize(), "illegal beg_bci"); 53 Assert.that(0 <= end_bci && end_bci <= _method.getCodeSize(), "illegal end_bci"); 54 } 55 // setup of iteration pointers 56 _bci = beg_bci; 57 _next_bci = beg_bci; 58 _end_bci = end_bci; 59 } 60 61 public void setStart(int beg_bci) { 62 setInterval(beg_bci, (int) _method.getCodeSize()); 63 } 64 65 // Iteration 66 public int next() { 67 int code; 68 // set reading position 69 _bci = _next_bci; 70 if (isLastBytecode()) { 71 // indicate end of bytecode stream 72 code = Bytecodes._illegal; 73 } else { 74 // get bytecode 75 int rawCode = Bytecodes.codeAt(_method, _bci); 76 code = 0; // Make javac happy 77 try { 78 code = Bytecodes.javaCode(rawCode); 79 } catch (AssertionFailure e) { 80 e.printStackTrace(); 81 Assert.that(false, "Failure occurred at bci " + _bci + " in method " + _method.externalNameAndSignature()); 82 } 83 84 // set next bytecode position 85 // 86 int l = Bytecodes.lengthFor(code); 87 if (l == 0) l = Bytecodes.lengthAt(_method, _bci); 88 _next_bci += l; 89 if (Assert.ASSERTS_ENABLED) { 90 Assert.that(_bci < _next_bci, "length must be > 0"); 91 } 92 // set attributes 93 _is_wide = false; 94 // check for special (uncommon) cases 95 if (code == Bytecodes._wide) { 96 code = _method.getBytecodeOrBPAt(_bci + 1); 97 _is_wide = true; 98 } 99 if (Assert.ASSERTS_ENABLED) { 100 Assert.that(Bytecodes.isJavaCode(code), "sanity check"); 101 } 102 } 103 _code = code; 104 return _code; 105 } 106 107 // Stream attributes 108 public Method method() { return _method; } 109 public int bci() { return _bci; } 110 public int nextBCI() { return _next_bci; } 111 public int endBCI() { return _end_bci; } 112 public int code() { return _code; } 113 public boolean isWide() { return _is_wide; } 114 public boolean isActiveBreakpoint() { return Bytecodes.isActiveBreakpointAt(_method, _bci); } 115 public boolean isLastBytecode() { return _next_bci >= _end_bci; } 116 117 // State changes 118 public void setNextBCI(int bci) { 119 if (Assert.ASSERTS_ENABLED) { 120 Assert.that(0 <= bci && bci <= _method.getCodeSize(), "illegal bci"); 121 } 122 _next_bci = bci; 123 } 124 125 // Bytecode-specific attributes 126 public int dest() { return bci() + _method.getBytecodeShortArg(bci() + 1); } 127 public int dest_w() { return bci() + _method.getBytecodeIntArg(bci() + 1); } 128 129 // Unsigned indices, widening 130 public int getIndex() { return (isWide()) 131 ? (_method.getBytecodeShortArg(bci() + 2) & 0xFFFF) 132 : (_method.getBytecodeOrBPAt(bci() + 1) & 0xFF); } 133 public int getIndexU1() { return _method.getBytecodeOrBPAt(bci() + 1) & 0xFF; } 134 public int getIndexU2() { return _method.getBytecodeShortArg(bci() + 1) & 0xFFFF; } 135 public int getIndexU4() { return _method.getNativeIntArg(bci() + 1); } 136 public boolean hasIndexU4() { return code() == Bytecodes._invokedynamic; } 137 138 public int getIndexU1Cpcache() { return _method.getBytecodeOrBPAt(bci() + 1) & 0xFF; } 139 public int getIndexU2Cpcache() { return _method.getNativeShortArg(bci() + 1) & 0xFFFF; } 140 141 // Fetch at absolute BCI (for manual parsing of certain bytecodes) 142 public int codeAt(int bci) { 143 return _method.getBytecodeOrBPAt(bci); 144 } 145 }