comparison src/share/vm/interpreter/bytecodeStream.hpp @ 1565:ab102d5d923e

6939207: refactor constant pool index processing Summary: Factored cleanup of instruction decode which prepares for enhanced ldc semantics. Reviewed-by: twisti
author jrose
date Sun, 23 May 2010 01:38:26 -0700
parents bd02caa94611
children de91a2f25c7e
comparison
equal deleted inserted replaced
1564:61b2245abf36 1565:ab102d5d923e
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 };