Mercurial > hg > truffle
annotate src/share/vm/interpreter/bytecode.cpp @ 9126:bc26f978b0ce
HotSpotResolvedObjectType: implement hasFinalizeSubclass() correctly
don't use the (wrong) cached value, but ask the runtime on each request.
Fixes regression on xml.* benchmarks @ specjvm2008. The problem was:
After the constructor of Object was deoptimized due to an assumption violation,
it was recompiled again after some time. However, on recompilation, the value
of hasFinalizeSubclass for the class was not updated and it was compiled again
with a, now wrong, assumption, which then triggers deoptimization again.
This was repeated until it hit the recompilation limit (defined by
PerMethodRecompilationCutoff), and therefore only executed by the interpreter
from now on, causing the performance regression.
author | Bernhard Urban <bernhard.urban@jku.at> |
---|---|
date | Mon, 15 Apr 2013 19:54:58 +0200 |
parents | da91efe96a93 |
children |
rev | line source |
---|---|
0 | 1 /* |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
2 * Copyright (c) 1997, 2012, 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:
1135
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1135
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:
1135
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "interpreter/bytecode.hpp" | |
27 #include "interpreter/linkResolver.hpp" | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
28 #include "oops/constantPool.hpp" |
1972 | 29 #include "oops/oop.inline.hpp" |
30 #include "runtime/fieldType.hpp" | |
31 #include "runtime/handles.inline.hpp" | |
32 #include "runtime/safepoint.hpp" | |
33 #include "runtime/signature.hpp" | |
0 | 34 |
35 // Implementation of Bytecode | |
36 | |
1565 | 37 #ifdef ASSERT |
38 | |
39 void Bytecode::assert_same_format_as(Bytecodes::Code testbc, bool is_wide) const { | |
40 Bytecodes::Code thisbc = Bytecodes::cast(byte_at(0)); | |
41 if (thisbc == Bytecodes::_breakpoint) return; // let the assertion fail silently | |
42 if (is_wide) { | |
43 assert(thisbc == Bytecodes::_wide, "expected a wide instruction"); | |
44 thisbc = Bytecodes::cast(byte_at(1)); | |
45 if (thisbc == Bytecodes::_breakpoint) return; | |
46 } | |
47 int thisflags = Bytecodes::flags(testbc, is_wide) & Bytecodes::_all_fmt_bits; | |
48 int testflags = Bytecodes::flags(thisbc, is_wide) & Bytecodes::_all_fmt_bits; | |
49 if (thisflags != testflags) | |
50 tty->print_cr("assert_same_format_as(%d) failed on bc=%d%s; %d != %d", | |
51 (int)testbc, (int)thisbc, (is_wide?"/wide":""), testflags, thisflags); | |
52 assert(thisflags == testflags, "expected format"); | |
53 } | |
54 | |
55 void Bytecode::assert_index_size(int size, Bytecodes::Code bc, bool is_wide) { | |
56 int have_fmt = (Bytecodes::flags(bc, is_wide) | |
57 & (Bytecodes::_fmt_has_u2 | Bytecodes::_fmt_has_u4 | | |
58 Bytecodes::_fmt_not_simple | | |
59 // Not an offset field: | |
60 Bytecodes::_fmt_has_o)); | |
61 int need_fmt = -1; | |
62 switch (size) { | |
63 case 1: need_fmt = 0; break; | |
64 case 2: need_fmt = Bytecodes::_fmt_has_u2; break; | |
65 case 4: need_fmt = Bytecodes::_fmt_has_u4; break; | |
66 } | |
67 if (is_wide) need_fmt |= Bytecodes::_fmt_not_simple; | |
68 if (have_fmt != need_fmt) { | |
69 tty->print_cr("assert_index_size %d: bc=%d%s %d != %d", size, bc, (is_wide?"/wide":""), have_fmt, need_fmt); | |
70 assert(have_fmt == need_fmt, "assert_index_size"); | |
71 } | |
72 } | |
73 | |
74 void Bytecode::assert_offset_size(int size, Bytecodes::Code bc, bool is_wide) { | |
75 int have_fmt = Bytecodes::flags(bc, is_wide) & Bytecodes::_all_fmt_bits; | |
76 int need_fmt = -1; | |
77 switch (size) { | |
78 case 2: need_fmt = Bytecodes::_fmt_bo2; break; | |
79 case 4: need_fmt = Bytecodes::_fmt_bo4; break; | |
80 } | |
81 if (is_wide) need_fmt |= Bytecodes::_fmt_not_simple; | |
82 if (have_fmt != need_fmt) { | |
83 tty->print_cr("assert_offset_size %d: bc=%d%s %d != %d", size, bc, (is_wide?"/wide":""), have_fmt, need_fmt); | |
84 assert(have_fmt == need_fmt, "assert_offset_size"); | |
85 } | |
86 } | |
87 | |
88 void Bytecode::assert_constant_size(int size, int where, Bytecodes::Code bc, bool is_wide) { | |
89 int have_fmt = Bytecodes::flags(bc, is_wide) & (Bytecodes::_all_fmt_bits | |
90 // Ignore any 'i' field (for iinc): | |
91 & ~Bytecodes::_fmt_has_i); | |
92 int need_fmt = -1; | |
93 switch (size) { | |
94 case 1: need_fmt = Bytecodes::_fmt_bc; break; | |
95 case 2: need_fmt = Bytecodes::_fmt_bc | Bytecodes::_fmt_has_u2; break; | |
96 } | |
97 if (is_wide) need_fmt |= Bytecodes::_fmt_not_simple; | |
98 int length = is_wide ? Bytecodes::wide_length_for(bc) : Bytecodes::length_for(bc); | |
99 if (have_fmt != need_fmt || where + size != length) { | |
100 tty->print_cr("assert_constant_size %d @%d: bc=%d%s %d != %d", size, where, bc, (is_wide?"/wide":""), have_fmt, need_fmt); | |
101 } | |
102 assert(have_fmt == need_fmt, "assert_constant_size"); | |
103 assert(where + size == length, "assert_constant_size oob"); | |
104 } | |
105 | |
106 void Bytecode::assert_native_index(Bytecodes::Code bc, bool is_wide) { | |
107 assert((Bytecodes::flags(bc, is_wide) & Bytecodes::_fmt_has_nbo) != 0, "native index"); | |
108 } | |
109 | |
110 #endif //ASSERT | |
0 | 111 |
112 // Implementation of Bytecode_tableupswitch | |
113 | |
114 int Bytecode_tableswitch::dest_offset_at(int i) const { | |
1565 | 115 return get_Java_u4_at(aligned_offset(1 + (3 + i)*jintSize)); |
0 | 116 } |
117 | |
118 | |
119 // Implementation of Bytecode_invoke | |
120 | |
121 void Bytecode_invoke::verify() const { | |
122 assert(is_valid(), "check invoke"); | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
123 assert(cpcache() != NULL, "do not call this from verifier or rewriter"); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
124 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
125 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
126 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
127 Symbol* Bytecode_member_ref::klass() const { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
128 return constants()->klass_ref_at_noresolve(index()); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
129 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
130 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
131 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
132 Symbol* Bytecode_member_ref::name() const { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
133 return constants()->name_ref_at(index()); |
0 | 134 } |
135 | |
136 | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2142
diff
changeset
|
137 Symbol* Bytecode_member_ref::signature() const { |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
138 return constants()->signature_ref_at(index()); |
0 | 139 } |
140 | |
141 | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2142
diff
changeset
|
142 BasicType Bytecode_member_ref::result_type() const { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2142
diff
changeset
|
143 ResultTypeFinder rts(signature()); |
0 | 144 rts.iterate(); |
145 return rts.type(); | |
146 } | |
147 | |
148 | |
149 methodHandle Bytecode_invoke::static_target(TRAPS) { | |
150 methodHandle m; | |
151 KlassHandle resolved_klass; | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
152 constantPoolHandle constants(THREAD, this->constants()); |
0 | 153 |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
154 Bytecodes::Code bc = invoke_code(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
155 LinkResolver::resolve_method_statically(m, resolved_klass, bc, constants, index(), CHECK_(methodHandle())); |
0 | 156 return m; |
157 } | |
158 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
159 Handle Bytecode_invoke::appendix(TRAPS) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
160 ConstantPoolCacheEntry* cpce = cpcache_entry(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
161 if (cpce->has_appendix()) |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
162 return Handle(THREAD, cpce->appendix_if_resolved(constants())); |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
163 return Handle(); // usual case |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
164 } |
0 | 165 |
1602 | 166 int Bytecode_member_ref::index() const { |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
167 // Note: Rewriter::rewrite changes the Java_u2 of an invokedynamic to a native_u4, |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
168 // at the same time it allocates per-call-site CP cache entries. |
1602 | 169 Bytecodes::Code rawc = code(); |
2142 | 170 if (has_index_u4(rawc)) |
171 return get_index_u4(rawc); | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
172 else |
2142 | 173 return get_index_u2_cpcache(rawc); |
0 | 174 } |
175 | |
1602 | 176 int Bytecode_member_ref::pool_index() const { |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
177 return cpcache_entry()->constant_pool_index(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
178 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
179 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
2177
diff
changeset
|
180 ConstantPoolCacheEntry* Bytecode_member_ref::cpcache_entry() const { |
1602 | 181 int index = this->index(); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
182 return cpcache()->entry_at(ConstantPool::decode_cpcache_index(index, true)); |
1602 | 183 } |
0 | 184 |
185 // Implementation of Bytecode_field | |
186 | |
187 void Bytecode_field::verify() const { | |
1602 | 188 assert(is_valid(), "check field"); |
0 | 189 } |
190 | |
191 | |
1602 | 192 // Implementation of Bytecode_loadconstant |
193 | |
194 int Bytecode_loadconstant::raw_index() const { | |
2142 | 195 Bytecodes::Code rawc = code(); |
1602 | 196 assert(rawc != Bytecodes::_wide, "verifier prevents this"); |
197 if (Bytecodes::java_code(rawc) == Bytecodes::_ldc) | |
2142 | 198 return get_index_u1(rawc); |
1602 | 199 else |
2142 | 200 return get_index_u2(rawc, false); |
0 | 201 } |
202 | |
1602 | 203 int Bytecode_loadconstant::pool_index() const { |
204 int index = raw_index(); | |
205 if (has_cache_index()) { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
206 return _method->constants()->object_to_cp_index(index); |
1602 | 207 } |
208 return index; | |
209 } | |
0 | 210 |
1602 | 211 BasicType Bytecode_loadconstant::result_type() const { |
212 int index = pool_index(); | |
213 constantTag tag = _method->constants()->tag_at(index); | |
214 return tag.basic_type(); | |
215 } | |
216 | |
217 oop Bytecode_loadconstant::resolve_constant(TRAPS) const { | |
218 assert(_method.not_null(), "must supply method to resolve constant"); | |
219 int index = raw_index(); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
220 ConstantPool* constants = _method->constants(); |
1602 | 221 if (has_cache_index()) { |
222 return constants->resolve_cached_constant_at(index, THREAD); | |
223 } else { | |
224 return constants->resolve_constant_at(index, THREAD); | |
1574 | 225 } |
0 | 226 } |
227 | |
228 //------------------------------------------------------------------------------ | |
229 // Non-product code | |
230 | |
231 #ifndef PRODUCT | |
232 | |
233 void Bytecode_lookupswitch::verify() const { | |
234 switch (Bytecodes::java_code(code())) { | |
235 case Bytecodes::_lookupswitch: | |
236 { int i = number_of_pairs() - 1; | |
237 while (i-- > 0) { | |
2142 | 238 assert(pair_at(i).match() < pair_at(i+1).match(), "unsorted table entries"); |
0 | 239 } |
240 } | |
241 break; | |
242 default: | |
243 fatal("not a lookupswitch bytecode"); | |
244 } | |
245 } | |
246 | |
247 void Bytecode_tableswitch::verify() const { | |
248 switch (Bytecodes::java_code(code())) { | |
249 case Bytecodes::_tableswitch: | |
250 { int lo = low_key(); | |
251 int hi = high_key(); | |
252 assert (hi >= lo, "incorrect hi/lo values in tableswitch"); | |
253 int i = hi - lo - 1 ; | |
254 while (i-- > 0) { | |
255 // no special check needed | |
256 } | |
257 } | |
258 break; | |
259 default: | |
260 fatal("not a tableswitch bytecode"); | |
261 } | |
262 } | |
263 | |
264 #endif |