Mercurial > hg > graal-compiler
annotate src/share/vm/classfile/stackMapFrame.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 | 4ee06e614636 |
children | 2373a1f4987c b2daaf70fab2 |
rev | line source |
---|---|
0 | 1 /* |
6605 | 2 * Copyright (c) 2003, 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:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
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:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "classfile/stackMapFrame.hpp" | |
27 #include "classfile/verifier.hpp" | |
28 #include "memory/resourceArea.hpp" | |
29 #include "oops/oop.inline.hpp" | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
30 #include "oops/symbol.hpp" |
1972 | 31 #include "runtime/handles.inline.hpp" |
32 #include "utilities/globalDefinitions.hpp" | |
0 | 33 |
34 StackMapFrame::StackMapFrame(u2 max_locals, u2 max_stack, ClassVerifier* v) : | |
6605 | 35 _offset(0), _locals_size(0), _stack_size(0), |
36 _stack_mark(0), _flags(0), _max_locals(max_locals), | |
37 _max_stack(max_stack), _verifier(v) { | |
0 | 38 Thread* thr = v->thread(); |
39 _locals = NEW_RESOURCE_ARRAY_IN_THREAD(thr, VerificationType, max_locals); | |
40 _stack = NEW_RESOURCE_ARRAY_IN_THREAD(thr, VerificationType, max_stack); | |
41 int32_t i; | |
42 for(i = 0; i < max_locals; i++) { | |
43 _locals[i] = VerificationType::bogus_type(); | |
44 } | |
45 for(i = 0; i < max_stack; i++) { | |
46 _stack[i] = VerificationType::bogus_type(); | |
47 } | |
48 } | |
49 | |
50 StackMapFrame* StackMapFrame::frame_in_exception_handler(u1 flags) { | |
51 Thread* thr = _verifier->thread(); | |
52 VerificationType* stack = NEW_RESOURCE_ARRAY_IN_THREAD(thr, VerificationType, 1); | |
53 StackMapFrame* frame = new StackMapFrame(_offset, flags, _locals_size, 0, _max_locals, _max_stack, _locals, stack, _verifier); | |
54 return frame; | |
55 } | |
56 | |
57 bool StackMapFrame::has_new_object() const { | |
58 int32_t i; | |
59 for (i = 0; i < _max_locals; i++) { | |
60 if (_locals[i].is_uninitialized()) { | |
61 return true; | |
62 } | |
63 } | |
64 for (i = 0; i < _stack_size; i++) { | |
65 if (_stack[i].is_uninitialized()) { | |
66 return true; | |
67 } | |
68 } | |
69 return false; | |
70 } | |
71 | |
72 void StackMapFrame::initialize_object( | |
73 VerificationType old_object, VerificationType new_object) { | |
74 int32_t i; | |
75 for (i = 0; i < _max_locals; i++) { | |
76 if (_locals[i].equals(old_object)) { | |
77 _locals[i] = new_object; | |
78 } | |
79 } | |
80 for (i = 0; i < _stack_size; i++) { | |
81 if (_stack[i].equals(old_object)) { | |
82 _stack[i] = new_object; | |
83 } | |
84 } | |
85 if (old_object == VerificationType::uninitialized_this_type()) { | |
86 // "this" has been initialized - reset flags | |
87 _flags = 0; | |
88 } | |
89 } | |
90 | |
91 VerificationType StackMapFrame::set_locals_from_arg( | |
92 const methodHandle m, VerificationType thisKlass, TRAPS) { | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
93 SignatureStream ss(m->signature()); |
0 | 94 int init_local_num = 0; |
95 if (!m->is_static()) { | |
96 init_local_num++; | |
97 // add one extra argument for instance method | |
98 if (m->name() == vmSymbols::object_initializer_name() && | |
99 thisKlass.name() != vmSymbols::java_lang_Object()) { | |
100 _locals[0] = VerificationType::uninitialized_this_type(); | |
101 _flags |= FLAG_THIS_UNINIT; | |
102 } else { | |
103 _locals[0] = thisKlass; | |
104 } | |
105 } | |
106 | |
107 // local num may be greater than size of parameters because long/double occupies two slots | |
108 while(!ss.at_return_type()) { | |
109 init_local_num += _verifier->change_sig_to_verificationType( | |
110 &ss, &_locals[init_local_num], | |
111 CHECK_VERIFY_(verifier(), VerificationType::bogus_type())); | |
112 ss.next(); | |
113 } | |
114 _locals_size = init_local_num; | |
115 | |
116 switch (ss.type()) { | |
117 case T_OBJECT: | |
118 case T_ARRAY: | |
119 { | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
120 Symbol* sig = ss.as_symbol(CHECK_(VerificationType::bogus_type())); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
121 // Create another symbol to save as signature stream unreferences |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
122 // this symbol. |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
123 Symbol* sig_copy = |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
124 verifier()->create_temporary_symbol(sig, 0, sig->utf8_length(), |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
125 CHECK_(VerificationType::bogus_type())); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
126 assert(sig_copy == sig, "symbols don't match"); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
127 return VerificationType::reference_type(sig_copy); |
0 | 128 } |
129 case T_INT: return VerificationType::integer_type(); | |
130 case T_BYTE: return VerificationType::byte_type(); | |
131 case T_CHAR: return VerificationType::char_type(); | |
132 case T_SHORT: return VerificationType::short_type(); | |
133 case T_BOOLEAN: return VerificationType::boolean_type(); | |
134 case T_FLOAT: return VerificationType::float_type(); | |
135 case T_DOUBLE: return VerificationType::double_type(); | |
136 case T_LONG: return VerificationType::long_type(); | |
137 case T_VOID: return VerificationType::bogus_type(); | |
138 default: | |
139 ShouldNotReachHere(); | |
140 } | |
141 return VerificationType::bogus_type(); | |
142 } | |
143 | |
144 void StackMapFrame::copy_locals(const StackMapFrame* src) { | |
145 int32_t len = src->locals_size() < _locals_size ? | |
146 src->locals_size() : _locals_size; | |
147 for (int32_t i = 0; i < len; i++) { | |
148 _locals[i] = src->locals()[i]; | |
149 } | |
150 } | |
151 | |
152 void StackMapFrame::copy_stack(const StackMapFrame* src) { | |
153 int32_t len = src->stack_size() < _stack_size ? | |
154 src->stack_size() : _stack_size; | |
155 for (int32_t i = 0; i < len; i++) { | |
156 _stack[i] = src->stack()[i]; | |
157 } | |
158 } | |
159 | |
6605 | 160 // Returns the location of the first mismatch, or 'len' if there are no |
161 // mismatches | |
162 int StackMapFrame::is_assignable_to( | |
0 | 163 VerificationType* from, VerificationType* to, int32_t len, TRAPS) const { |
6605 | 164 int32_t i = 0; |
165 for (i = 0; i < len; i++) { | |
166 if (!to[i].is_assignable_from(from[i], verifier(), THREAD)) { | |
167 break; | |
0 | 168 } |
169 } | |
6605 | 170 return i; |
0 | 171 } |
172 | |
2303
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
173 bool StackMapFrame::has_flag_match_exception( |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
174 const StackMapFrame* target) const { |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
175 // We allow flags of {UninitThis} to assign to {} if-and-only-if the |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
176 // target frame does not depend upon the current type. |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
177 // This is slightly too strict, as we need only enforce that the |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
178 // slots that were initialized by the <init> (the things that were |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
179 // UninitializedThis before initialize_object() converted them) are unused. |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
180 // However we didn't save that information so we'll enforce this upon |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
181 // anything that might have been initialized. This is a rare situation |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
182 // and javac never generates code that would end up here, but some profilers |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
183 // (such as NetBeans) might, when adding exception handlers in <init> |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
184 // methods to cover the invokespecial instruction. See 7020118. |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
185 |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
186 assert(max_locals() == target->max_locals() && |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
187 stack_size() == target->stack_size(), "StackMap sizes must match"); |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
188 |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
189 VerificationType top = VerificationType::top_type(); |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
190 VerificationType this_type = verifier()->current_type(); |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
191 |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
192 if (!flag_this_uninit() || target->flags() != 0) { |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
193 return false; |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
194 } |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
195 |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
196 for (int i = 0; i < target->locals_size(); ++i) { |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
197 if (locals()[i] == this_type && target->locals()[i] != top) { |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
198 return false; |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
199 } |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
200 } |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
201 |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
202 for (int i = 0; i < target->stack_size(); ++i) { |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
203 if (stack()[i] == this_type && target->stack()[i] != top) { |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
204 return false; |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
205 } |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
206 } |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
207 |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
208 return true; |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
209 } |
c1a6154012c8
7020118: Alter frame assignability to allow for exception handler coverage of invokespecial <init>
kamg
parents:
2177
diff
changeset
|
210 |
2472
7144a1d6e0a9
7030388: JCK test failed to reject invalid class check01304m10n.
kamg
parents:
2303
diff
changeset
|
211 bool StackMapFrame::is_assignable_to( |
6605 | 212 const StackMapFrame* target, bool is_exception_handler, |
213 ErrorContext* ctx, TRAPS) const { | |
214 if (_max_locals != target->max_locals()) { | |
215 *ctx = ErrorContext::locals_size_mismatch( | |
216 _offset, (StackMapFrame*)this, (StackMapFrame*)target); | |
217 return false; | |
218 } | |
219 if (_stack_size != target->stack_size()) { | |
220 *ctx = ErrorContext::stack_size_mismatch( | |
221 _offset, (StackMapFrame*)this, (StackMapFrame*)target); | |
0 | 222 return false; |
223 } | |
224 // Only need to compare type elements up to target->locals() or target->stack(). | |
225 // The remaining type elements in this state can be ignored because they are | |
226 // assignable to bogus type. | |
6605 | 227 int mismatch_loc; |
228 mismatch_loc = is_assignable_to( | |
229 _locals, target->locals(), target->locals_size(), THREAD); | |
230 if (mismatch_loc != target->locals_size()) { | |
231 *ctx = ErrorContext::bad_type(target->offset(), | |
232 TypeOrigin::local(mismatch_loc, (StackMapFrame*)this), | |
233 TypeOrigin::sm_local(mismatch_loc, (StackMapFrame*)target)); | |
234 return false; | |
235 } | |
236 mismatch_loc = is_assignable_to(_stack, target->stack(), _stack_size, THREAD); | |
237 if (mismatch_loc != _stack_size) { | |
238 *ctx = ErrorContext::bad_type(target->offset(), | |
239 TypeOrigin::stack(mismatch_loc, (StackMapFrame*)this), | |
240 TypeOrigin::sm_stack(mismatch_loc, (StackMapFrame*)target)); | |
241 return false; | |
242 } | |
243 | |
0 | 244 bool match_flags = (_flags | target->flags()) == target->flags(); |
6605 | 245 if (match_flags || is_exception_handler && has_flag_match_exception(target)) { |
246 return true; | |
247 } else { | |
248 *ctx = ErrorContext::bad_flags(target->offset(), | |
249 (StackMapFrame*)this, (StackMapFrame*)target); | |
250 return false; | |
251 } | |
0 | 252 } |
253 | |
254 VerificationType StackMapFrame::pop_stack_ex(VerificationType type, TRAPS) { | |
255 if (_stack_size <= 0) { | |
6605 | 256 verifier()->verify_error( |
257 ErrorContext::stack_underflow(_offset, this), | |
258 "Operand stack underflow"); | |
0 | 259 return VerificationType::bogus_type(); |
260 } | |
261 VerificationType top = _stack[--_stack_size]; | |
262 bool subtype = type.is_assignable_from( | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
263 top, verifier(), CHECK_(VerificationType::bogus_type())); |
0 | 264 if (!subtype) { |
6605 | 265 verifier()->verify_error( |
266 ErrorContext::bad_type(_offset, stack_top_ctx(), | |
267 TypeOrigin::implicit(type)), | |
268 "Bad type on operand stack"); | |
0 | 269 return VerificationType::bogus_type(); |
270 } | |
271 return top; | |
272 } | |
273 | |
274 VerificationType StackMapFrame::get_local( | |
275 int32_t index, VerificationType type, TRAPS) { | |
276 if (index >= _max_locals) { | |
6605 | 277 verifier()->verify_error( |
278 ErrorContext::bad_local_index(_offset, index), | |
279 "Local variable table overflow"); | |
0 | 280 return VerificationType::bogus_type(); |
281 } | |
282 bool subtype = type.is_assignable_from(_locals[index], | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
283 verifier(), CHECK_(VerificationType::bogus_type())); |
0 | 284 if (!subtype) { |
6605 | 285 verifier()->verify_error( |
286 ErrorContext::bad_type(_offset, | |
287 TypeOrigin::local(index, this), | |
288 TypeOrigin::implicit(type)), | |
289 "Bad local variable type"); | |
0 | 290 return VerificationType::bogus_type(); |
291 } | |
292 if(index >= _locals_size) { _locals_size = index + 1; } | |
293 return _locals[index]; | |
294 } | |
295 | |
296 void StackMapFrame::get_local_2( | |
297 int32_t index, VerificationType type1, VerificationType type2, TRAPS) { | |
298 assert(type1.is_long() || type1.is_double(), "must be long/double"); | |
299 assert(type2.is_long2() || type2.is_double2(), "must be long/double_2"); | |
300 if (index >= _locals_size - 1) { | |
6605 | 301 verifier()->verify_error( |
302 ErrorContext::bad_local_index(_offset, index), | |
303 "get long/double overflows locals"); | |
0 | 304 return; |
305 } | |
6605 | 306 bool subtype = type1.is_assignable_from(_locals[index], verifier(), CHECK); |
307 if (!subtype) { | |
308 verifier()->verify_error( | |
309 ErrorContext::bad_type(_offset, | |
310 TypeOrigin::local(index, this), TypeOrigin::implicit(type1)), | |
311 "Bad local variable type"); | |
312 } else { | |
313 subtype = type2.is_assignable_from(_locals[index + 1], verifier(), CHECK); | |
314 if (!subtype) { | |
315 /* Unreachable? All local store routines convert a split long or double | |
316 * into a TOP during the store. So we should never end up seeing an | |
317 * orphaned half. */ | |
318 verifier()->verify_error( | |
319 ErrorContext::bad_type(_offset, | |
320 TypeOrigin::local(index + 1, this), TypeOrigin::implicit(type2)), | |
321 "Bad local variable type"); | |
322 } | |
0 | 323 } |
324 } | |
325 | |
326 void StackMapFrame::set_local(int32_t index, VerificationType type, TRAPS) { | |
327 assert(!type.is_check(), "Must be a real type"); | |
328 if (index >= _max_locals) { | |
6605 | 329 verifier()->verify_error( |
330 ErrorContext::bad_local_index(_offset, index), | |
331 "Local variable table overflow"); | |
0 | 332 return; |
333 } | |
334 // If type at index is double or long, set the next location to be unusable | |
335 if (_locals[index].is_double() || _locals[index].is_long()) { | |
336 assert((index + 1) < _locals_size, "Local variable table overflow"); | |
337 _locals[index + 1] = VerificationType::bogus_type(); | |
338 } | |
339 // If type at index is double_2 or long_2, set the previous location to be unusable | |
340 if (_locals[index].is_double2() || _locals[index].is_long2()) { | |
341 assert(index >= 1, "Local variable table underflow"); | |
342 _locals[index - 1] = VerificationType::bogus_type(); | |
343 } | |
344 _locals[index] = type; | |
345 if (index >= _locals_size) { | |
346 #ifdef ASSERT | |
347 for (int i=_locals_size; i<index; i++) { | |
348 assert(_locals[i] == VerificationType::bogus_type(), | |
349 "holes must be bogus type"); | |
350 } | |
351 #endif | |
352 _locals_size = index + 1; | |
353 } | |
354 } | |
355 | |
356 void StackMapFrame::set_local_2( | |
357 int32_t index, VerificationType type1, VerificationType type2, TRAPS) { | |
358 assert(type1.is_long() || type1.is_double(), "must be long/double"); | |
359 assert(type2.is_long2() || type2.is_double2(), "must be long/double_2"); | |
360 if (index >= _max_locals - 1) { | |
6605 | 361 verifier()->verify_error( |
362 ErrorContext::bad_local_index(_offset, index), | |
363 "Local variable table overflow"); | |
0 | 364 return; |
365 } | |
366 // If type at index+1 is double or long, set the next location to be unusable | |
367 if (_locals[index+1].is_double() || _locals[index+1].is_long()) { | |
368 assert((index + 2) < _locals_size, "Local variable table overflow"); | |
369 _locals[index + 2] = VerificationType::bogus_type(); | |
370 } | |
371 // If type at index is double_2 or long_2, set the previous location to be unusable | |
372 if (_locals[index].is_double2() || _locals[index].is_long2()) { | |
373 assert(index >= 1, "Local variable table underflow"); | |
374 _locals[index - 1] = VerificationType::bogus_type(); | |
375 } | |
376 _locals[index] = type1; | |
377 _locals[index+1] = type2; | |
378 if (index >= _locals_size - 1) { | |
379 #ifdef ASSERT | |
380 for (int i=_locals_size; i<index; i++) { | |
381 assert(_locals[i] == VerificationType::bogus_type(), | |
382 "holes must be bogus type"); | |
383 } | |
384 #endif | |
385 _locals_size = index + 2; | |
386 } | |
387 } | |
388 | |
6605 | 389 TypeOrigin StackMapFrame::stack_top_ctx() { |
390 return TypeOrigin::stack(_stack_size, this); | |
0 | 391 } |
392 | |
6605 | 393 void StackMapFrame::print_on(outputStream* str) const { |
394 str->indent().print_cr("bci: @%d", _offset); | |
395 str->indent().print_cr("flags: {%s }", | |
396 flag_this_uninit() ? " flagThisUninit" : ""); | |
397 str->indent().print("locals: {"); | |
398 for (int32_t i = 0; i < _locals_size; ++i) { | |
399 str->print(" "); | |
400 _locals[i].print_on(str); | |
401 if (i != _locals_size - 1) { | |
402 str->print(","); | |
403 } | |
404 } | |
405 str->print_cr(" }"); | |
406 str->indent().print("stack: {"); | |
407 for (int32_t j = 0; j < _stack_size; ++j) { | |
408 str->print(" "); | |
409 _stack[j].print_on(str); | |
410 if (j != _stack_size - 1) { | |
411 str->print(","); | |
412 } | |
413 } | |
414 str->print_cr(" }"); | |
415 } |