Mercurial > hg > truffle
annotate src/share/vm/interpreter/bytecode.hpp @ 4181:319860ae697a
Simplify FrameMap: make offsets of spill slots and outgoing parameters independent so that they can be allocated at the same time, eliminating the separate phases. This makes the separate StackBlock unnecesary. Change CiStackSlot to use byte offsets instead of spill slot index. This makes CiTarget.spillSlotSize unnecessary.
author | Christian Wimmer <Christian.Wimmer@Oracle.com> |
---|---|
date | Mon, 02 Jan 2012 14:16:08 -0800 |
parents | e342a5110bed |
children | 1d7922586cf6 |
rev | line source |
---|---|
0 | 1 /* |
2142 | 2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1138
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1138
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1138
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #ifndef SHARE_VM_INTERPRETER_BYTECODE_HPP |
26 #define SHARE_VM_INTERPRETER_BYTECODE_HPP | |
27 | |
28 #include "interpreter/bytecodes.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 | |
2192
b92c45f2bc75
7016023: Enable building ARM and PPC from src/closed repository
bobv
parents:
2177
diff
changeset
|
40 #ifdef TARGET_ARCH_arm |
b92c45f2bc75
7016023: Enable building ARM and PPC from src/closed repository
bobv
parents:
2177
diff
changeset
|
41 # include "bytes_arm.hpp" |
b92c45f2bc75
7016023: Enable building ARM and PPC from src/closed repository
bobv
parents:
2177
diff
changeset
|
42 #endif |
b92c45f2bc75
7016023: Enable building ARM and PPC from src/closed repository
bobv
parents:
2177
diff
changeset
|
43 #ifdef TARGET_ARCH_ppc |
b92c45f2bc75
7016023: Enable building ARM and PPC from src/closed repository
bobv
parents:
2177
diff
changeset
|
44 # include "bytes_ppc.hpp" |
b92c45f2bc75
7016023: Enable building ARM and PPC from src/closed repository
bobv
parents:
2177
diff
changeset
|
45 #endif |
1972 | 46 |
2142 | 47 class ciBytecodeStream; |
48 | |
49 // The base class for different kinds of bytecode abstractions. | |
50 // Provides the primitive operations to manipulate code relative | |
51 // to the bcp. | |
0 | 52 |
2142 | 53 class Bytecode: public StackObj { |
54 protected: | |
55 const address _bcp; | |
56 const Bytecodes::Code _code; | |
57 | |
0 | 58 // Address computation |
2142 | 59 address addr_at (int offset) const { return (address)_bcp + offset; } |
60 u_char byte_at(int offset) const { return *addr_at(offset); } | |
0 | 61 address aligned_addr_at (int offset) const { return (address)round_to((intptr_t)addr_at(offset), jintSize); } |
62 int aligned_offset (int offset) const { return aligned_addr_at(offset) - addr_at(0); } | |
63 | |
1565 | 64 // Word access: |
65 int get_Java_u2_at (int offset) const { return Bytes::get_Java_u2(addr_at(offset)); } | |
66 int get_Java_u4_at (int offset) const { return Bytes::get_Java_u4(addr_at(offset)); } | |
67 int get_native_u2_at (int offset) const { return Bytes::get_native_u2(addr_at(offset)); } | |
68 int get_native_u4_at (int offset) const { return Bytes::get_native_u4(addr_at(offset)); } | |
0 | 69 |
70 public: | |
2142 | 71 Bytecode(methodOop method, address bcp): _bcp(bcp), _code(Bytecodes::code_at(method, addr_at(0))) { |
72 assert(method != NULL, "this form requires a valid methodOop"); | |
73 } | |
74 // Defined in ciStreams.hpp | |
75 inline Bytecode(const ciBytecodeStream* stream, address bcp = NULL); | |
0 | 76 |
2142 | 77 // Attributes |
78 address bcp() const { return _bcp; } | |
79 int instruction_size() const { return Bytecodes::length_for_code_at(_code, bcp()); } | |
80 | |
81 Bytecodes::Code code() const { return _code; } | |
0 | 82 Bytecodes::Code java_code() const { return Bytecodes::java_code(code()); } |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
83 |
1565 | 84 // Static functions for parsing bytecodes in place. |
85 int get_index_u1(Bytecodes::Code bc) const { | |
86 assert_same_format_as(bc); assert_index_size(1, bc); | |
87 return *(jubyte*)addr_at(1); | |
88 } | |
89 int get_index_u2(Bytecodes::Code bc, bool is_wide = false) const { | |
90 assert_same_format_as(bc, is_wide); assert_index_size(2, bc, is_wide); | |
91 address p = addr_at(is_wide ? 2 : 1); | |
92 if (can_use_native_byte_order(bc, is_wide)) | |
2142 | 93 return Bytes::get_native_u2(p); |
1565 | 94 else return Bytes::get_Java_u2(p); |
95 } | |
1602 | 96 int get_index_u1_cpcache(Bytecodes::Code bc) const { |
97 assert_same_format_as(bc); assert_index_size(1, bc); | |
98 return *(jubyte*)addr_at(1) + constantPoolOopDesc::CPCACHE_INDEX_TAG; | |
99 } | |
1565 | 100 int get_index_u2_cpcache(Bytecodes::Code bc) const { |
101 assert_same_format_as(bc); assert_index_size(2, bc); assert_native_index(bc); | |
1602 | 102 return Bytes::get_native_u2(addr_at(1)) + constantPoolOopDesc::CPCACHE_INDEX_TAG; |
1565 | 103 } |
104 int get_index_u4(Bytecodes::Code bc) const { | |
105 assert_same_format_as(bc); assert_index_size(4, bc); | |
106 assert(can_use_native_byte_order(bc), ""); | |
107 return Bytes::get_native_u4(addr_at(1)); | |
108 } | |
109 bool has_index_u4(Bytecodes::Code bc) const { | |
110 return bc == Bytecodes::_invokedynamic; | |
111 } | |
112 | |
113 int get_offset_s2(Bytecodes::Code bc) const { | |
114 assert_same_format_as(bc); assert_offset_size(2, bc); | |
115 return (jshort) Bytes::get_Java_u2(addr_at(1)); | |
116 } | |
117 int get_offset_s4(Bytecodes::Code bc) const { | |
118 assert_same_format_as(bc); assert_offset_size(4, bc); | |
119 return (jint) Bytes::get_Java_u4(addr_at(1)); | |
120 } | |
121 | |
122 int get_constant_u1(int offset, Bytecodes::Code bc) const { | |
123 assert_same_format_as(bc); assert_constant_size(1, offset, bc); | |
124 return *(jbyte*)addr_at(offset); | |
125 } | |
126 int get_constant_u2(int offset, Bytecodes::Code bc, bool is_wide = false) const { | |
127 assert_same_format_as(bc, is_wide); assert_constant_size(2, offset, bc, is_wide); | |
128 return (jshort) Bytes::get_Java_u2(addr_at(offset)); | |
129 } | |
130 | |
131 // These are used locally and also from bytecode streams. | |
132 void assert_same_format_as(Bytecodes::Code testbc, bool is_wide = false) const NOT_DEBUG_RETURN; | |
133 static void assert_index_size(int required_size, Bytecodes::Code bc, bool is_wide = false) NOT_DEBUG_RETURN; | |
134 static void assert_offset_size(int required_size, Bytecodes::Code bc, bool is_wide = false) NOT_DEBUG_RETURN; | |
135 static void assert_constant_size(int required_size, int where, Bytecodes::Code bc, bool is_wide = false) NOT_DEBUG_RETURN; | |
136 static void assert_native_index(Bytecodes::Code bc, bool is_wide = false) NOT_DEBUG_RETURN; | |
137 static bool can_use_native_byte_order(Bytecodes::Code bc, bool is_wide = false) { | |
138 return (!Bytes::is_Java_byte_ordering_different() || Bytecodes::native_byte_order(bc /*, is_wide*/)); | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
139 } |
0 | 140 }; |
141 | |
142 | |
143 // Abstractions for lookupswitch bytecode | |
2142 | 144 class LookupswitchPair VALUE_OBJ_CLASS_SPEC { |
0 | 145 private: |
2142 | 146 const address _bcp; |
147 | |
148 address addr_at (int offset) const { return _bcp + offset; } | |
149 int get_Java_u4_at (int offset) const { return Bytes::get_Java_u4(addr_at(offset)); } | |
0 | 150 |
151 public: | |
2142 | 152 LookupswitchPair(address bcp): _bcp(bcp) {} |
1565 | 153 int match() const { return get_Java_u4_at(0 * jintSize); } |
154 int offset() const { return get_Java_u4_at(1 * jintSize); } | |
0 | 155 }; |
156 | |
157 | |
158 class Bytecode_lookupswitch: public Bytecode { | |
159 public: | |
2142 | 160 Bytecode_lookupswitch(methodOop method, address bcp): Bytecode(method, bcp) { verify(); } |
161 // Defined in ciStreams.hpp | |
162 inline Bytecode_lookupswitch(const ciBytecodeStream* stream); | |
0 | 163 void verify() const PRODUCT_RETURN; |
164 | |
165 // Attributes | |
1565 | 166 int default_offset() const { return get_Java_u4_at(aligned_offset(1 + 0*jintSize)); } |
167 int number_of_pairs() const { return get_Java_u4_at(aligned_offset(1 + 1*jintSize)); } | |
2142 | 168 LookupswitchPair pair_at(int i) const { |
169 assert(0 <= i && i < number_of_pairs(), "pair index out of bounds"); | |
170 return LookupswitchPair(aligned_addr_at(1 + (1 + i)*2*jintSize)); | |
171 } | |
0 | 172 }; |
173 | |
174 class Bytecode_tableswitch: public Bytecode { | |
175 public: | |
2142 | 176 Bytecode_tableswitch(methodOop method, address bcp): Bytecode(method, bcp) { verify(); } |
177 // Defined in ciStreams.hpp | |
178 inline Bytecode_tableswitch(const ciBytecodeStream* stream); | |
0 | 179 void verify() const PRODUCT_RETURN; |
180 | |
181 // Attributes | |
1565 | 182 int default_offset() const { return get_Java_u4_at(aligned_offset(1 + 0*jintSize)); } |
183 int low_key() const { return get_Java_u4_at(aligned_offset(1 + 1*jintSize)); } | |
184 int high_key() const { return get_Java_u4_at(aligned_offset(1 + 2*jintSize)); } | |
0 | 185 int dest_offset_at(int i) const; |
186 int length() { return high_key()-low_key()+1; } | |
187 }; | |
188 | |
1602 | 189 // Common code for decoding invokes and field references. |
0 | 190 |
2142 | 191 class Bytecode_member_ref: public Bytecode { |
0 | 192 protected: |
2142 | 193 const methodHandle _method; // method containing the bytecode |
0 | 194 |
2142 | 195 Bytecode_member_ref(methodHandle method, int bci) : Bytecode(method(), method()->bcp_from(bci)), _method(method) {} |
196 | |
197 methodHandle method() const { return _method; } | |
1602 | 198 |
199 public: | |
200 int index() const; // cache index (loaded from instruction) | |
201 int pool_index() const; // constant pool index | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2142
diff
changeset
|
202 Symbol* name() const; // returns the name of the method or field |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2142
diff
changeset
|
203 Symbol* signature() const; // returns the signature of the method or field |
1602 | 204 |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2142
diff
changeset
|
205 BasicType result_type() const; // returns the result type of the getfield or invoke |
1602 | 206 }; |
207 | |
208 // Abstraction for invoke_{virtual, static, interface, special} | |
209 | |
210 class Bytecode_invoke: public Bytecode_member_ref { | |
211 protected: | |
2142 | 212 // Constructor that skips verification |
213 Bytecode_invoke(methodHandle method, int bci, bool unused) : Bytecode_member_ref(method, bci) {} | |
0 | 214 |
215 public: | |
2142 | 216 Bytecode_invoke(methodHandle method, int bci) : Bytecode_member_ref(method, bci) { verify(); } |
0 | 217 void verify() const; |
218 | |
219 // Attributes | |
220 methodHandle static_target(TRAPS); // "specified" method (from constant pool) | |
221 | |
222 // Testers | |
1602 | 223 bool is_invokeinterface() const { return java_code() == Bytecodes::_invokeinterface; } |
224 bool is_invokevirtual() const { return java_code() == Bytecodes::_invokevirtual; } | |
225 bool is_invokestatic() const { return java_code() == Bytecodes::_invokestatic; } | |
226 bool is_invokespecial() const { return java_code() == Bytecodes::_invokespecial; } | |
227 bool is_invokedynamic() const { return java_code() == Bytecodes::_invokedynamic; } | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
228 |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1135
diff
changeset
|
229 bool has_receiver() const { return !is_invokestatic() && !is_invokedynamic(); } |
0 | 230 |
231 bool is_valid() const { return is_invokeinterface() || | |
232 is_invokevirtual() || | |
233 is_invokestatic() || | |
1135
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
844
diff
changeset
|
234 is_invokespecial() || |
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
844
diff
changeset
|
235 is_invokedynamic(); } |
0 | 236 |
4055
e342a5110bed
7106774: JSR 292: nightly test inlineMHTarget fails with wrong result
twisti
parents:
2192
diff
changeset
|
237 bool is_method_handle_invoke() const { |
e342a5110bed
7106774: JSR 292: nightly test inlineMHTarget fails with wrong result
twisti
parents:
2192
diff
changeset
|
238 return (is_invokedynamic() || |
e342a5110bed
7106774: JSR 292: nightly test inlineMHTarget fails with wrong result
twisti
parents:
2192
diff
changeset
|
239 (is_invokevirtual() && |
e342a5110bed
7106774: JSR 292: nightly test inlineMHTarget fails with wrong result
twisti
parents:
2192
diff
changeset
|
240 method()->constants()->klass_ref_at_noresolve(index()) == vmSymbols::java_lang_invoke_MethodHandle() && |
e342a5110bed
7106774: JSR 292: nightly test inlineMHTarget fails with wrong result
twisti
parents:
2192
diff
changeset
|
241 methodOopDesc::is_method_handle_invoke_name(name()))); |
e342a5110bed
7106774: JSR 292: nightly test inlineMHTarget fails with wrong result
twisti
parents:
2192
diff
changeset
|
242 } |
e342a5110bed
7106774: JSR 292: nightly test inlineMHTarget fails with wrong result
twisti
parents:
2192
diff
changeset
|
243 |
2142 | 244 // Helper to skip verification. Used is_valid() to check if the result is really an invoke |
245 inline friend Bytecode_invoke Bytecode_invoke_check(methodHandle method, int bci); | |
0 | 246 }; |
247 | |
2142 | 248 inline Bytecode_invoke Bytecode_invoke_check(methodHandle method, int bci) { |
249 return Bytecode_invoke(method, bci, false); | |
0 | 250 } |
251 | |
252 | |
1602 | 253 // Abstraction for all field accesses (put/get field/static) |
254 class Bytecode_field: public Bytecode_member_ref { | |
2142 | 255 public: |
256 Bytecode_field(methodHandle method, int bci) : Bytecode_member_ref(method, bci) { verify(); } | |
1602 | 257 |
258 // Testers | |
259 bool is_getfield() const { return java_code() == Bytecodes::_getfield; } | |
260 bool is_putfield() const { return java_code() == Bytecodes::_putfield; } | |
261 bool is_getstatic() const { return java_code() == Bytecodes::_getstatic; } | |
262 bool is_putstatic() const { return java_code() == Bytecodes::_putstatic; } | |
263 | |
264 bool is_getter() const { return is_getfield() || is_getstatic(); } | |
265 bool is_static() const { return is_getstatic() || is_putstatic(); } | |
266 | |
267 bool is_valid() const { return is_getfield() || | |
268 is_putfield() || | |
269 is_getstatic() || | |
270 is_putstatic(); } | |
0 | 271 void verify() const; |
272 }; | |
273 | |
274 // Abstraction for checkcast | |
275 class Bytecode_checkcast: public Bytecode { | |
276 public: | |
2142 | 277 Bytecode_checkcast(methodOop method, address bcp): Bytecode(method, bcp) { verify(); } |
0 | 278 void verify() const { assert(Bytecodes::java_code(code()) == Bytecodes::_checkcast, "check checkcast"); } |
279 | |
280 // Returns index | |
1565 | 281 long index() const { return get_index_u2(Bytecodes::_checkcast); }; |
0 | 282 }; |
283 | |
284 // Abstraction for instanceof | |
285 class Bytecode_instanceof: public Bytecode { | |
286 public: | |
2142 | 287 Bytecode_instanceof(methodOop method, address bcp): Bytecode(method, bcp) { verify(); } |
0 | 288 void verify() const { assert(code() == Bytecodes::_instanceof, "check instanceof"); } |
289 | |
290 // Returns index | |
1565 | 291 long index() const { return get_index_u2(Bytecodes::_instanceof); }; |
0 | 292 }; |
293 | |
294 class Bytecode_new: public Bytecode { | |
295 public: | |
2142 | 296 Bytecode_new(methodOop method, address bcp): Bytecode(method, bcp) { verify(); } |
0 | 297 void verify() const { assert(java_code() == Bytecodes::_new, "check new"); } |
298 | |
299 // Returns index | |
1565 | 300 long index() const { return get_index_u2(Bytecodes::_new); }; |
0 | 301 }; |
302 | |
303 class Bytecode_multianewarray: public Bytecode { | |
304 public: | |
2142 | 305 Bytecode_multianewarray(methodOop method, address bcp): Bytecode(method, bcp) { verify(); } |
0 | 306 void verify() const { assert(java_code() == Bytecodes::_multianewarray, "check new"); } |
307 | |
308 // Returns index | |
1565 | 309 long index() const { return get_index_u2(Bytecodes::_multianewarray); }; |
0 | 310 }; |
311 | |
312 class Bytecode_anewarray: public Bytecode { | |
313 public: | |
2142 | 314 Bytecode_anewarray(methodOop method, address bcp): Bytecode(method, bcp) { verify(); } |
0 | 315 void verify() const { assert(java_code() == Bytecodes::_anewarray, "check anewarray"); } |
316 | |
317 // Returns index | |
1565 | 318 long index() const { return get_index_u2(Bytecodes::_anewarray); }; |
0 | 319 }; |
320 | |
321 // Abstraction for ldc, ldc_w and ldc2_w | |
2142 | 322 class Bytecode_loadconstant: public Bytecode { |
1602 | 323 private: |
2142 | 324 const methodHandle _method; |
1602 | 325 |
326 int raw_index() const; | |
327 | |
0 | 328 public: |
2142 | 329 Bytecode_loadconstant(methodHandle method, int bci): Bytecode(method(), method->bcp_from(bci)), _method(method) { verify(); } |
1602 | 330 |
0 | 331 void verify() const { |
1602 | 332 assert(_method.not_null(), "must supply method"); |
0 | 333 Bytecodes::Code stdc = Bytecodes::java_code(code()); |
334 assert(stdc == Bytecodes::_ldc || | |
335 stdc == Bytecodes::_ldc_w || | |
336 stdc == Bytecodes::_ldc2_w, "load constant"); | |
337 } | |
338 | |
1602 | 339 // Only non-standard bytecodes (fast_aldc) have CP cache indexes. |
340 bool has_cache_index() const { return code() >= Bytecodes::number_of_java_codes; } | |
0 | 341 |
1602 | 342 int pool_index() const; // index into constant pool |
343 int cache_index() const { // index into CP cache (or -1 if none) | |
344 return has_cache_index() ? raw_index() : -1; | |
345 } | |
346 | |
347 BasicType result_type() const; // returns the result type of the ldc | |
348 | |
349 oop resolve_constant(TRAPS) const; | |
0 | 350 }; |
351 | |
1972 | 352 #endif // SHARE_VM_INTERPRETER_BYTECODE_HPP |