1 /* |
|
2 * Copyright (c) 2012, 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 #include "precompiled.hpp" |
|
26 |
|
27 #include "classfile/genericSignatures.hpp" |
|
28 #include "classfile/symbolTable.hpp" |
|
29 #include "classfile/systemDictionary.hpp" |
|
30 #include "memory/resourceArea.hpp" |
|
31 |
|
32 namespace generic { |
|
33 |
|
34 // Helper class for parsing the generic signature Symbol in klass and methods |
|
35 class DescriptorStream : public ResourceObj { |
|
36 private: |
|
37 Symbol* _symbol; |
|
38 int _offset; |
|
39 int _mark; |
|
40 const char* _parse_error; |
|
41 |
|
42 void set_parse_error(const char* error) { |
|
43 assert(error != NULL, "Can't set NULL error string"); |
|
44 _parse_error = error; |
|
45 } |
|
46 |
|
47 public: |
|
48 DescriptorStream(Symbol* sym) |
|
49 : _symbol(sym), _offset(0), _mark(-1), _parse_error(NULL) {} |
|
50 |
|
51 const char* parse_error() const { |
|
52 return _parse_error; |
|
53 } |
|
54 |
|
55 bool at_end() { return _offset >= _symbol->utf8_length(); } |
|
56 |
|
57 char peek() { |
|
58 if (at_end()) { |
|
59 set_parse_error("Peeking past end of signature"); |
|
60 return '\0'; |
|
61 } else { |
|
62 return _symbol->byte_at(_offset); |
|
63 } |
|
64 } |
|
65 |
|
66 char read() { |
|
67 if (at_end()) { |
|
68 set_parse_error("Reading past end of signature"); |
|
69 return '\0'; |
|
70 } else { |
|
71 return _symbol->byte_at(_offset++); |
|
72 } |
|
73 } |
|
74 |
|
75 void read(char expected) { |
|
76 char c = read(); |
|
77 assert_char(c, expected, 0); |
|
78 } |
|
79 |
|
80 void assert_char(char c, char expected, int pos = -1) { |
|
81 if (c != expected) { |
|
82 const char* fmt = "Parse error at %d: expected %c but got %c"; |
|
83 size_t len = strlen(fmt) + 5; |
|
84 char* buffer = NEW_RESOURCE_ARRAY(char, len); |
|
85 jio_snprintf(buffer, len, fmt, _offset + pos, expected, c); |
|
86 set_parse_error(buffer); |
|
87 } |
|
88 } |
|
89 |
|
90 void push(char c) { |
|
91 assert(c == _symbol->byte_at(_offset - 1), "Pushing back wrong value"); |
|
92 --_offset; |
|
93 } |
|
94 |
|
95 void expect_end() { |
|
96 if (!at_end()) { |
|
97 set_parse_error("Unexpected data trailing signature"); |
|
98 } |
|
99 } |
|
100 |
|
101 bool has_mark() { return _mark != -1; } |
|
102 |
|
103 void set_mark() { |
|
104 _mark = _offset; |
|
105 } |
|
106 |
|
107 Identifier* identifier_from_mark() { |
|
108 assert(has_mark(), "Mark should be set"); |
|
109 if (!has_mark()) { |
|
110 set_parse_error("Expected mark to be set"); |
|
111 return NULL; |
|
112 } else { |
|
113 Identifier* id = new Identifier(_symbol, _mark, _offset - 1); |
|
114 _mark = -1; |
|
115 return id; |
|
116 } |
|
117 } |
|
118 }; |
|
119 |
|
120 |
|
121 #define CHECK_FOR_PARSE_ERROR() \ |
|
122 if (STREAM->parse_error() != NULL) { \ |
|
123 if (VerifyGenericSignatures) { \ |
|
124 fatal(STREAM->parse_error()); \ |
|
125 } \ |
|
126 return NULL; \ |
|
127 } (void)0 |
|
128 |
|
129 #define READ() STREAM->read(); CHECK_FOR_PARSE_ERROR() |
|
130 #define PEEK() STREAM->peek(); CHECK_FOR_PARSE_ERROR() |
|
131 #define PUSH(c) STREAM->push(c) |
|
132 #define EXPECT(c) STREAM->read(c); CHECK_FOR_PARSE_ERROR() |
|
133 #define EXPECTED(c, ch) STREAM->assert_char(c, ch); CHECK_FOR_PARSE_ERROR() |
|
134 #define EXPECT_END() STREAM->expect_end(); CHECK_FOR_PARSE_ERROR() |
|
135 |
|
136 #define CHECK_STREAM STREAM); CHECK_FOR_PARSE_ERROR(); ((void)0 |
|
137 |
|
138 #ifndef PRODUCT |
|
139 void Identifier::print_on(outputStream* str) const { |
|
140 for (int i = _begin; i < _end; ++i) { |
|
141 str->print("%c", (char)_sym->byte_at(i)); |
|
142 } |
|
143 } |
|
144 #endif // ndef PRODUCT |
|
145 |
|
146 bool Identifier::equals(Identifier* other) { |
|
147 if (_sym == other->_sym && _begin == other->_begin && _end == other->_end) { |
|
148 return true; |
|
149 } else if (_end - _begin != other->_end - other->_begin) { |
|
150 return false; |
|
151 } else { |
|
152 size_t len = _end - _begin; |
|
153 char* addr = ((char*)_sym->bytes()) + _begin; |
|
154 char* oaddr = ((char*)other->_sym->bytes()) + other->_begin; |
|
155 return strncmp(addr, oaddr, len) == 0; |
|
156 } |
|
157 } |
|
158 |
|
159 bool Identifier::equals(Symbol* sym) { |
|
160 Identifier id(sym, 0, sym->utf8_length()); |
|
161 return equals(&id); |
|
162 } |
|
163 |
|
164 /** |
|
165 * A formal type parameter may be found in the the enclosing class, but it could |
|
166 * also come from an enclosing method or outer class, in the case of inner-outer |
|
167 * classes or anonymous classes. For example: |
|
168 * |
|
169 * class Outer<T,V> { |
|
170 * class Inner<W> { |
|
171 * void m(T t, V v, W w); |
|
172 * } |
|
173 * } |
|
174 * |
|
175 * In this case, the type variables in m()'s signature are not all found in the |
|
176 * immediate enclosing class (Inner). class Inner has only type parameter W, |
|
177 * but it's outer_class field will reference Outer's descriptor which contains |
|
178 * T & V (no outer_method in this case). |
|
179 * |
|
180 * If you have an anonymous class, it has both an enclosing method *and* an |
|
181 * enclosing class where type parameters can be declared: |
|
182 * |
|
183 * class MOuter<T> { |
|
184 * <V> void bar(V v) { |
|
185 * Runnable r = new Runnable() { |
|
186 * public void run() {} |
|
187 * public void foo(T t, V v) { ... } |
|
188 * }; |
|
189 * } |
|
190 * } |
|
191 * |
|
192 * In this case, foo will be a member of some class, Runnable$1, which has no |
|
193 * formal parameters itself, but has an outer_method (bar()) which provides |
|
194 * type parameter V, and an outer class MOuter with type parameter T. |
|
195 * |
|
196 * It is also possible that the outer class is itself an inner class to some |
|
197 * other class (or an anonymous class with an enclosing method), so we need to |
|
198 * follow the outer_class/outer_method chain to it's end when looking for a |
|
199 * type parameter. |
|
200 */ |
|
201 TypeParameter* Descriptor::find_type_parameter(Identifier* id, int* depth) { |
|
202 |
|
203 int current_depth = 0; |
|
204 |
|
205 MethodDescriptor* outer_method = as_method_signature(); |
|
206 ClassDescriptor* outer_class = as_class_signature(); |
|
207 |
|
208 if (outer_class == NULL) { // 'this' is a method signature; use the holder |
|
209 outer_class = outer_method->outer_class(); |
|
210 } |
|
211 |
|
212 while (outer_method != NULL || outer_class != NULL) { |
|
213 if (outer_method != NULL) { |
|
214 for (int i = 0; i < outer_method->type_parameters().length(); ++i) { |
|
215 TypeParameter* p = outer_method->type_parameters().at(i); |
|
216 if (p->identifier()->equals(id)) { |
|
217 *depth = -1; // indicates this this is a method parameter |
|
218 return p; |
|
219 } |
|
220 } |
|
221 } |
|
222 if (outer_class != NULL) { |
|
223 for (int i = 0; i < outer_class->type_parameters().length(); ++i) { |
|
224 TypeParameter* p = outer_class->type_parameters().at(i); |
|
225 if (p->identifier()->equals(id)) { |
|
226 *depth = current_depth; |
|
227 return p; |
|
228 } |
|
229 } |
|
230 outer_method = outer_class->outer_method(); |
|
231 outer_class = outer_class->outer_class(); |
|
232 ++current_depth; |
|
233 } |
|
234 } |
|
235 |
|
236 if (VerifyGenericSignatures) { |
|
237 fatal("Could not resolve identifier"); |
|
238 } |
|
239 |
|
240 return NULL; |
|
241 } |
|
242 |
|
243 ClassDescriptor* ClassDescriptor::parse_generic_signature(Klass* klass, TRAPS) { |
|
244 return parse_generic_signature(klass, NULL, CHECK_NULL); |
|
245 } |
|
246 |
|
247 ClassDescriptor* ClassDescriptor::parse_generic_signature( |
|
248 Klass* klass, Symbol* original_name, TRAPS) { |
|
249 |
|
250 InstanceKlass* ik = InstanceKlass::cast(klass); |
|
251 Symbol* sym = ik->generic_signature(); |
|
252 |
|
253 ClassDescriptor* spec; |
|
254 |
|
255 if (sym == NULL || (spec = ClassDescriptor::parse_generic_signature(sym)) == NULL) { |
|
256 spec = ClassDescriptor::placeholder(ik); |
|
257 } |
|
258 |
|
259 u2 outer_index = get_outer_class_index(ik, CHECK_NULL); |
|
260 if (outer_index != 0) { |
|
261 if (original_name == NULL) { |
|
262 original_name = ik->name(); |
|
263 } |
|
264 Handle class_loader = Handle(THREAD, ik->class_loader()); |
|
265 Handle protection_domain = Handle(THREAD, ik->protection_domain()); |
|
266 |
|
267 Symbol* outer_name = ik->constants()->klass_name_at(outer_index); |
|
268 Klass* outer = SystemDictionary::find( |
|
269 outer_name, class_loader, protection_domain, CHECK_NULL); |
|
270 if (outer == NULL && !THREAD->is_Compiler_thread()) { |
|
271 if (outer_name == ik->super()->name()) { |
|
272 outer = SystemDictionary::resolve_super_or_fail(original_name, outer_name, |
|
273 class_loader, protection_domain, |
|
274 false, CHECK_NULL); |
|
275 } |
|
276 else { |
|
277 outer = SystemDictionary::resolve_or_fail(outer_name, class_loader, |
|
278 protection_domain, false, CHECK_NULL); |
|
279 } |
|
280 } |
|
281 |
|
282 InstanceKlass* outer_ik; |
|
283 ClassDescriptor* outer_spec = NULL; |
|
284 if (outer == NULL) { |
|
285 outer_spec = ClassDescriptor::placeholder(ik); |
|
286 assert(false, "Outer class not loaded and not loadable from here"); |
|
287 } else { |
|
288 outer_ik = InstanceKlass::cast(outer); |
|
289 outer_spec = parse_generic_signature(outer, original_name, CHECK_NULL); |
|
290 } |
|
291 spec->set_outer_class(outer_spec); |
|
292 |
|
293 u2 encl_method_idx = ik->enclosing_method_method_index(); |
|
294 if (encl_method_idx != 0 && outer_ik != NULL) { |
|
295 ConstantPool* cp = ik->constants(); |
|
296 u2 name_index = cp->name_ref_index_at(encl_method_idx); |
|
297 u2 sig_index = cp->signature_ref_index_at(encl_method_idx); |
|
298 Symbol* name = cp->symbol_at(name_index); |
|
299 Symbol* sig = cp->symbol_at(sig_index); |
|
300 Method* m = outer_ik->find_method(name, sig); |
|
301 if (m != NULL) { |
|
302 Symbol* gsig = m->generic_signature(); |
|
303 if (gsig != NULL) { |
|
304 MethodDescriptor* gms = MethodDescriptor::parse_generic_signature(gsig, outer_spec); |
|
305 spec->set_outer_method(gms); |
|
306 } |
|
307 } else if (VerifyGenericSignatures) { |
|
308 ResourceMark rm; |
|
309 stringStream ss; |
|
310 ss.print("Could not find method %s %s in class %s", |
|
311 name->as_C_string(), sig->as_C_string(), outer_name->as_C_string()); |
|
312 fatal(ss.as_string()); |
|
313 } |
|
314 } |
|
315 } |
|
316 |
|
317 spec->bind_variables_to_parameters(); |
|
318 return spec; |
|
319 } |
|
320 |
|
321 ClassDescriptor* ClassDescriptor::placeholder(InstanceKlass* klass) { |
|
322 GrowableArray<TypeParameter*> formals; |
|
323 GrowableArray<ClassType*> interfaces; |
|
324 ClassType* super_type = NULL; |
|
325 |
|
326 Klass* super_klass = klass->super(); |
|
327 if (super_klass != NULL) { |
|
328 InstanceKlass* super = InstanceKlass::cast(super_klass); |
|
329 super_type = ClassType::from_symbol(super->name()); |
|
330 } |
|
331 |
|
332 for (int i = 0; i < klass->local_interfaces()->length(); ++i) { |
|
333 InstanceKlass* iface = InstanceKlass::cast(klass->local_interfaces()->at(i)); |
|
334 interfaces.append(ClassType::from_symbol(iface->name())); |
|
335 } |
|
336 return new ClassDescriptor(formals, super_type, interfaces); |
|
337 } |
|
338 |
|
339 ClassDescriptor* ClassDescriptor::parse_generic_signature(Symbol* sym) { |
|
340 |
|
341 DescriptorStream ds(sym); |
|
342 DescriptorStream* STREAM = &ds; |
|
343 |
|
344 GrowableArray<TypeParameter*> parameters(8); |
|
345 char c = READ(); |
|
346 if (c == '<') { |
|
347 c = READ(); |
|
348 while (c != '>') { |
|
349 PUSH(c); |
|
350 TypeParameter* ftp = TypeParameter::parse_generic_signature(CHECK_STREAM); |
|
351 parameters.append(ftp); |
|
352 c = READ(); |
|
353 } |
|
354 } else { |
|
355 PUSH(c); |
|
356 } |
|
357 |
|
358 EXPECT('L'); |
|
359 ClassType* super = ClassType::parse_generic_signature(CHECK_STREAM); |
|
360 |
|
361 GrowableArray<ClassType*> signatures(2); |
|
362 while (!STREAM->at_end()) { |
|
363 EXPECT('L'); |
|
364 ClassType* iface = ClassType::parse_generic_signature(CHECK_STREAM); |
|
365 signatures.append(iface); |
|
366 } |
|
367 |
|
368 EXPECT_END(); |
|
369 |
|
370 return new ClassDescriptor(parameters, super, signatures); |
|
371 } |
|
372 |
|
373 #ifndef PRODUCT |
|
374 void ClassDescriptor::print_on(outputStream* str) const { |
|
375 str->indent().print_cr("ClassDescriptor {"); |
|
376 { |
|
377 streamIndentor si(str); |
|
378 if (_type_parameters.length() > 0) { |
|
379 str->indent().print_cr("Formals {"); |
|
380 { |
|
381 streamIndentor si(str); |
|
382 for (int i = 0; i < _type_parameters.length(); ++i) { |
|
383 _type_parameters.at(i)->print_on(str); |
|
384 } |
|
385 } |
|
386 str->indent().print_cr("}"); |
|
387 } |
|
388 if (_super != NULL) { |
|
389 str->indent().print_cr("Superclass: "); |
|
390 { |
|
391 streamIndentor si(str); |
|
392 _super->print_on(str); |
|
393 } |
|
394 } |
|
395 if (_interfaces.length() > 0) { |
|
396 str->indent().print_cr("SuperInterfaces: {"); |
|
397 { |
|
398 streamIndentor si(str); |
|
399 for (int i = 0; i < _interfaces.length(); ++i) { |
|
400 _interfaces.at(i)->print_on(str); |
|
401 } |
|
402 } |
|
403 str->indent().print_cr("}"); |
|
404 } |
|
405 if (_outer_method != NULL) { |
|
406 str->indent().print_cr("Outer Method: {"); |
|
407 { |
|
408 streamIndentor si(str); |
|
409 _outer_method->print_on(str); |
|
410 } |
|
411 str->indent().print_cr("}"); |
|
412 } |
|
413 if (_outer_class != NULL) { |
|
414 str->indent().print_cr("Outer Class: {"); |
|
415 { |
|
416 streamIndentor si(str); |
|
417 _outer_class->print_on(str); |
|
418 } |
|
419 str->indent().print_cr("}"); |
|
420 } |
|
421 } |
|
422 str->indent().print_cr("}"); |
|
423 } |
|
424 #endif // ndef PRODUCT |
|
425 |
|
426 ClassType* ClassDescriptor::interface_desc(Symbol* sym) { |
|
427 for (int i = 0; i < _interfaces.length(); ++i) { |
|
428 if (_interfaces.at(i)->identifier()->equals(sym)) { |
|
429 return _interfaces.at(i); |
|
430 } |
|
431 } |
|
432 if (VerifyGenericSignatures) { |
|
433 fatal("Did not find expected interface"); |
|
434 } |
|
435 return NULL; |
|
436 } |
|
437 |
|
438 void ClassDescriptor::bind_variables_to_parameters() { |
|
439 if (_outer_class != NULL) { |
|
440 _outer_class->bind_variables_to_parameters(); |
|
441 } |
|
442 if (_outer_method != NULL) { |
|
443 _outer_method->bind_variables_to_parameters(); |
|
444 } |
|
445 for (int i = 0; i < _type_parameters.length(); ++i) { |
|
446 _type_parameters.at(i)->bind_variables_to_parameters(this, i); |
|
447 } |
|
448 if (_super != NULL) { |
|
449 _super->bind_variables_to_parameters(this); |
|
450 } |
|
451 for (int i = 0; i < _interfaces.length(); ++i) { |
|
452 _interfaces.at(i)->bind_variables_to_parameters(this); |
|
453 } |
|
454 } |
|
455 |
|
456 ClassDescriptor* ClassDescriptor::canonicalize(Context* ctx) { |
|
457 |
|
458 GrowableArray<TypeParameter*> type_params(_type_parameters.length()); |
|
459 for (int i = 0; i < _type_parameters.length(); ++i) { |
|
460 type_params.append(_type_parameters.at(i)->canonicalize(ctx, 0)); |
|
461 } |
|
462 |
|
463 ClassDescriptor* outer = _outer_class == NULL ? NULL : |
|
464 _outer_class->canonicalize(ctx); |
|
465 |
|
466 ClassType* super = _super == NULL ? NULL : _super->canonicalize(ctx, 0); |
|
467 |
|
468 GrowableArray<ClassType*> interfaces(_interfaces.length()); |
|
469 for (int i = 0; i < _interfaces.length(); ++i) { |
|
470 interfaces.append(_interfaces.at(i)->canonicalize(ctx, 0)); |
|
471 } |
|
472 |
|
473 MethodDescriptor* md = _outer_method == NULL ? NULL : |
|
474 _outer_method->canonicalize(ctx); |
|
475 |
|
476 return new ClassDescriptor(type_params, super, interfaces, outer, md); |
|
477 } |
|
478 |
|
479 u2 ClassDescriptor::get_outer_class_index(InstanceKlass* klass, TRAPS) { |
|
480 int inner_index = InstanceKlass::inner_class_inner_class_info_offset; |
|
481 int outer_index = InstanceKlass::inner_class_outer_class_info_offset; |
|
482 int name_offset = InstanceKlass::inner_class_inner_name_offset; |
|
483 int next_offset = InstanceKlass::inner_class_next_offset; |
|
484 |
|
485 if (klass->inner_classes() == NULL || klass->inner_classes()->length() == 0) { |
|
486 // No inner class info => no declaring class |
|
487 return 0; |
|
488 } |
|
489 |
|
490 Array<u2>* i_icls = klass->inner_classes(); |
|
491 ConstantPool* i_cp = klass->constants(); |
|
492 int i_length = i_icls->length(); |
|
493 |
|
494 // Find inner_klass attribute |
|
495 for (int i = 0; i + next_offset < i_length; i += next_offset) { |
|
496 u2 ioff = i_icls->at(i + inner_index); |
|
497 u2 ooff = i_icls->at(i + outer_index); |
|
498 u2 noff = i_icls->at(i + name_offset); |
|
499 if (ioff != 0) { |
|
500 // Check to see if the name matches the class we're looking for |
|
501 // before attempting to find the class. |
|
502 if (i_cp->klass_name_at_matches(klass, ioff) && ooff != 0) { |
|
503 return ooff; |
|
504 } |
|
505 } |
|
506 } |
|
507 |
|
508 // It may be anonymous; try for that. |
|
509 u2 encl_method_class_idx = klass->enclosing_method_class_index(); |
|
510 if (encl_method_class_idx != 0) { |
|
511 return encl_method_class_idx; |
|
512 } |
|
513 |
|
514 return 0; |
|
515 } |
|
516 |
|
517 MethodDescriptor* MethodDescriptor::parse_generic_signature(Method* m, ClassDescriptor* outer) { |
|
518 Symbol* generic_sig = m->generic_signature(); |
|
519 MethodDescriptor* md = NULL; |
|
520 if (generic_sig == NULL || (md = parse_generic_signature(generic_sig, outer)) == NULL) { |
|
521 md = parse_generic_signature(m->signature(), outer); |
|
522 } |
|
523 assert(md != NULL, "Could not parse method signature"); |
|
524 md->bind_variables_to_parameters(); |
|
525 return md; |
|
526 } |
|
527 |
|
528 MethodDescriptor* MethodDescriptor::parse_generic_signature(Symbol* sym, ClassDescriptor* outer) { |
|
529 |
|
530 DescriptorStream ds(sym); |
|
531 DescriptorStream* STREAM = &ds; |
|
532 |
|
533 GrowableArray<TypeParameter*> params(8); |
|
534 char c = READ(); |
|
535 if (c == '<') { |
|
536 c = READ(); |
|
537 while (c != '>') { |
|
538 PUSH(c); |
|
539 TypeParameter* ftp = TypeParameter::parse_generic_signature(CHECK_STREAM); |
|
540 params.append(ftp); |
|
541 c = READ(); |
|
542 } |
|
543 } else { |
|
544 PUSH(c); |
|
545 } |
|
546 |
|
547 EXPECT('('); |
|
548 |
|
549 GrowableArray<Type*> parameters(8); |
|
550 c = READ(); |
|
551 while (c != ')') { |
|
552 PUSH(c); |
|
553 Type* arg = Type::parse_generic_signature(CHECK_STREAM); |
|
554 parameters.append(arg); |
|
555 c = READ(); |
|
556 } |
|
557 |
|
558 Type* rt = Type::parse_generic_signature(CHECK_STREAM); |
|
559 |
|
560 GrowableArray<Type*> throws; |
|
561 while (!STREAM->at_end()) { |
|
562 EXPECT('^'); |
|
563 Type* spec = Type::parse_generic_signature(CHECK_STREAM); |
|
564 throws.append(spec); |
|
565 } |
|
566 |
|
567 return new MethodDescriptor(params, outer, parameters, rt, throws); |
|
568 } |
|
569 |
|
570 void MethodDescriptor::bind_variables_to_parameters() { |
|
571 for (int i = 0; i < _type_parameters.length(); ++i) { |
|
572 _type_parameters.at(i)->bind_variables_to_parameters(this, i); |
|
573 } |
|
574 for (int i = 0; i < _parameters.length(); ++i) { |
|
575 _parameters.at(i)->bind_variables_to_parameters(this); |
|
576 } |
|
577 _return_type->bind_variables_to_parameters(this); |
|
578 for (int i = 0; i < _throws.length(); ++i) { |
|
579 _throws.at(i)->bind_variables_to_parameters(this); |
|
580 } |
|
581 } |
|
582 |
|
583 bool MethodDescriptor::covariant_match(MethodDescriptor* other, Context* ctx) { |
|
584 |
|
585 if (_parameters.length() == other->_parameters.length()) { |
|
586 for (int i = 0; i < _parameters.length(); ++i) { |
|
587 if (!_parameters.at(i)->covariant_match(other->_parameters.at(i), ctx)) { |
|
588 return false; |
|
589 } |
|
590 } |
|
591 |
|
592 if (_return_type->as_primitive() != NULL) { |
|
593 return _return_type->covariant_match(other->_return_type, ctx); |
|
594 } else { |
|
595 // return type is a reference |
|
596 return other->_return_type->as_class() != NULL || |
|
597 other->_return_type->as_variable() != NULL || |
|
598 other->_return_type->as_array() != NULL; |
|
599 } |
|
600 } else { |
|
601 return false; |
|
602 } |
|
603 } |
|
604 |
|
605 MethodDescriptor* MethodDescriptor::canonicalize(Context* ctx) { |
|
606 |
|
607 GrowableArray<TypeParameter*> type_params(_type_parameters.length()); |
|
608 for (int i = 0; i < _type_parameters.length(); ++i) { |
|
609 type_params.append(_type_parameters.at(i)->canonicalize(ctx, 0)); |
|
610 } |
|
611 |
|
612 ClassDescriptor* outer = _outer_class == NULL ? NULL : |
|
613 _outer_class->canonicalize(ctx); |
|
614 |
|
615 GrowableArray<Type*> params(_parameters.length()); |
|
616 for (int i = 0; i < _parameters.length(); ++i) { |
|
617 params.append(_parameters.at(i)->canonicalize(ctx, 0)); |
|
618 } |
|
619 |
|
620 Type* rt = _return_type->canonicalize(ctx, 0); |
|
621 |
|
622 GrowableArray<Type*> throws(_throws.length()); |
|
623 for (int i = 0; i < _throws.length(); ++i) { |
|
624 throws.append(_throws.at(i)->canonicalize(ctx, 0)); |
|
625 } |
|
626 |
|
627 return new MethodDescriptor(type_params, outer, params, rt, throws); |
|
628 } |
|
629 |
|
630 #ifndef PRODUCT |
|
631 TempNewSymbol MethodDescriptor::reify_signature(Context* ctx, TRAPS) { |
|
632 stringStream ss(256); |
|
633 |
|
634 ss.print("("); |
|
635 for (int i = 0; i < _parameters.length(); ++i) { |
|
636 _parameters.at(i)->reify_signature(&ss, ctx); |
|
637 } |
|
638 ss.print(")"); |
|
639 _return_type->reify_signature(&ss, ctx); |
|
640 return SymbolTable::new_symbol(ss.base(), (int)ss.size(), THREAD); |
|
641 } |
|
642 |
|
643 void MethodDescriptor::print_on(outputStream* str) const { |
|
644 str->indent().print_cr("MethodDescriptor {"); |
|
645 { |
|
646 streamIndentor si(str); |
|
647 if (_type_parameters.length() > 0) { |
|
648 str->indent().print_cr("Formals: {"); |
|
649 { |
|
650 streamIndentor si(str); |
|
651 for (int i = 0; i < _type_parameters.length(); ++i) { |
|
652 _type_parameters.at(i)->print_on(str); |
|
653 } |
|
654 } |
|
655 str->indent().print_cr("}"); |
|
656 } |
|
657 str->indent().print_cr("Parameters: {"); |
|
658 { |
|
659 streamIndentor si(str); |
|
660 for (int i = 0; i < _parameters.length(); ++i) { |
|
661 _parameters.at(i)->print_on(str); |
|
662 } |
|
663 } |
|
664 str->indent().print_cr("}"); |
|
665 str->indent().print_cr("Return Type: "); |
|
666 { |
|
667 streamIndentor si(str); |
|
668 _return_type->print_on(str); |
|
669 } |
|
670 |
|
671 if (_throws.length() > 0) { |
|
672 str->indent().print_cr("Throws: {"); |
|
673 { |
|
674 streamIndentor si(str); |
|
675 for (int i = 0; i < _throws.length(); ++i) { |
|
676 _throws.at(i)->print_on(str); |
|
677 } |
|
678 } |
|
679 str->indent().print_cr("}"); |
|
680 } |
|
681 } |
|
682 str->indent().print_cr("}"); |
|
683 } |
|
684 #endif // ndef PRODUCT |
|
685 |
|
686 TypeParameter* TypeParameter::parse_generic_signature(DescriptorStream* STREAM) { |
|
687 STREAM->set_mark(); |
|
688 char c = READ(); |
|
689 while (c != ':') { |
|
690 c = READ(); |
|
691 } |
|
692 |
|
693 Identifier* id = STREAM->identifier_from_mark(); |
|
694 |
|
695 ClassType* class_bound = NULL; |
|
696 GrowableArray<ClassType*> interface_bounds(8); |
|
697 |
|
698 c = READ(); |
|
699 if (c != '>') { |
|
700 if (c != ':') { |
|
701 EXPECTED(c, 'L'); |
|
702 class_bound = ClassType::parse_generic_signature(CHECK_STREAM); |
|
703 c = READ(); |
|
704 } |
|
705 |
|
706 while (c == ':') { |
|
707 EXPECT('L'); |
|
708 ClassType* fts = ClassType::parse_generic_signature(CHECK_STREAM); |
|
709 interface_bounds.append(fts); |
|
710 c = READ(); |
|
711 } |
|
712 } |
|
713 PUSH(c); |
|
714 |
|
715 return new TypeParameter(id, class_bound, interface_bounds); |
|
716 } |
|
717 |
|
718 void TypeParameter::bind_variables_to_parameters(Descriptor* sig, int position) { |
|
719 if (_class_bound != NULL) { |
|
720 _class_bound->bind_variables_to_parameters(sig); |
|
721 } |
|
722 for (int i = 0; i < _interface_bounds.length(); ++i) { |
|
723 _interface_bounds.at(i)->bind_variables_to_parameters(sig); |
|
724 } |
|
725 _position = position; |
|
726 } |
|
727 |
|
728 Type* TypeParameter::resolve( |
|
729 Context* ctx, int inner_depth, int ctx_depth) { |
|
730 |
|
731 if (inner_depth == -1) { |
|
732 // This indicates that the parameter is a method type parameter, which |
|
733 // isn't resolveable using the class hierarchy context |
|
734 return bound(); |
|
735 } |
|
736 |
|
737 ClassType* provider = ctx->at_depth(ctx_depth); |
|
738 if (provider != NULL) { |
|
739 for (int i = 0; i < inner_depth && provider != NULL; ++i) { |
|
740 provider = provider->outer_class(); |
|
741 } |
|
742 if (provider != NULL) { |
|
743 TypeArgument* arg = provider->type_argument_at(_position); |
|
744 if (arg != NULL) { |
|
745 Type* value = arg->lower_bound(); |
|
746 return value->canonicalize(ctx, ctx_depth + 1); |
|
747 } |
|
748 } |
|
749 } |
|
750 |
|
751 return bound(); |
|
752 } |
|
753 |
|
754 TypeParameter* TypeParameter::canonicalize(Context* ctx, int ctx_depth) { |
|
755 ClassType* bound = _class_bound == NULL ? NULL : |
|
756 _class_bound->canonicalize(ctx, ctx_depth); |
|
757 |
|
758 GrowableArray<ClassType*> ifaces(_interface_bounds.length()); |
|
759 for (int i = 0; i < _interface_bounds.length(); ++i) { |
|
760 ifaces.append(_interface_bounds.at(i)->canonicalize(ctx, ctx_depth)); |
|
761 } |
|
762 |
|
763 TypeParameter* ret = new TypeParameter(_identifier, bound, ifaces); |
|
764 ret->_position = _position; |
|
765 return ret; |
|
766 } |
|
767 |
|
768 ClassType* TypeParameter::bound() { |
|
769 if (_class_bound != NULL) { |
|
770 return _class_bound; |
|
771 } |
|
772 |
|
773 if (_interface_bounds.length() == 1) { |
|
774 return _interface_bounds.at(0); |
|
775 } |
|
776 |
|
777 return ClassType::java_lang_Object(); // TODO: investigate this case |
|
778 } |
|
779 |
|
780 #ifndef PRODUCT |
|
781 void TypeParameter::print_on(outputStream* str) const { |
|
782 str->indent().print_cr("Formal: {"); |
|
783 { |
|
784 streamIndentor si(str); |
|
785 |
|
786 str->indent().print("Identifier: "); |
|
787 _identifier->print_on(str); |
|
788 str->print_cr(""); |
|
789 if (_class_bound != NULL) { |
|
790 str->indent().print_cr("Class Bound: "); |
|
791 streamIndentor si(str); |
|
792 _class_bound->print_on(str); |
|
793 } |
|
794 if (_interface_bounds.length() > 0) { |
|
795 str->indent().print_cr("Interface Bounds: {"); |
|
796 { |
|
797 streamIndentor si(str); |
|
798 for (int i = 0; i < _interface_bounds.length(); ++i) { |
|
799 _interface_bounds.at(i)->print_on(str); |
|
800 } |
|
801 } |
|
802 str->indent().print_cr("}"); |
|
803 } |
|
804 str->indent().print_cr("Ordinal Position: %d", _position); |
|
805 } |
|
806 str->indent().print_cr("}"); |
|
807 } |
|
808 #endif // ndef PRODUCT |
|
809 |
|
810 Type* Type::parse_generic_signature(DescriptorStream* STREAM) { |
|
811 char c = READ(); |
|
812 switch (c) { |
|
813 case 'L': |
|
814 return ClassType::parse_generic_signature(CHECK_STREAM); |
|
815 case 'T': |
|
816 return TypeVariable::parse_generic_signature(CHECK_STREAM); |
|
817 case '[': |
|
818 return ArrayType::parse_generic_signature(CHECK_STREAM); |
|
819 default: |
|
820 return new PrimitiveType(c); |
|
821 } |
|
822 } |
|
823 |
|
824 Identifier* ClassType::parse_generic_signature_simple(GrowableArray<TypeArgument*>* args, |
|
825 bool* has_inner, DescriptorStream* STREAM) { |
|
826 STREAM->set_mark(); |
|
827 |
|
828 char c = READ(); |
|
829 while (c != ';' && c != '.' && c != '<') { c = READ(); } |
|
830 Identifier* id = STREAM->identifier_from_mark(); |
|
831 |
|
832 if (c == '<') { |
|
833 c = READ(); |
|
834 while (c != '>') { |
|
835 PUSH(c); |
|
836 TypeArgument* arg = TypeArgument::parse_generic_signature(CHECK_STREAM); |
|
837 args->append(arg); |
|
838 c = READ(); |
|
839 } |
|
840 c = READ(); |
|
841 } |
|
842 |
|
843 *has_inner = (c == '.'); |
|
844 if (!(*has_inner)) { |
|
845 EXPECTED(c, ';'); |
|
846 } |
|
847 |
|
848 return id; |
|
849 } |
|
850 |
|
851 ClassType* ClassType::parse_generic_signature(DescriptorStream* STREAM) { |
|
852 return parse_generic_signature(NULL, CHECK_STREAM); |
|
853 } |
|
854 |
|
855 ClassType* ClassType::parse_generic_signature(ClassType* outer, DescriptorStream* STREAM) { |
|
856 GrowableArray<TypeArgument*> args; |
|
857 ClassType* gct = NULL; |
|
858 bool has_inner = false; |
|
859 |
|
860 Identifier* id = parse_generic_signature_simple(&args, &has_inner, STREAM); |
|
861 if (id != NULL) { |
|
862 gct = new ClassType(id, args, outer); |
|
863 |
|
864 if (has_inner) { |
|
865 gct = parse_generic_signature(gct, CHECK_STREAM); |
|
866 } |
|
867 } |
|
868 return gct; |
|
869 } |
|
870 |
|
871 ClassType* ClassType::from_symbol(Symbol* sym) { |
|
872 assert(sym != NULL, "Must not be null"); |
|
873 GrowableArray<TypeArgument*> args; |
|
874 Identifier* id = new Identifier(sym, 0, sym->utf8_length()); |
|
875 return new ClassType(id, args, NULL); |
|
876 } |
|
877 |
|
878 ClassType* ClassType::java_lang_Object() { |
|
879 return from_symbol(vmSymbols::java_lang_Object()); |
|
880 } |
|
881 |
|
882 void ClassType::bind_variables_to_parameters(Descriptor* sig) { |
|
883 for (int i = 0; i < _type_arguments.length(); ++i) { |
|
884 _type_arguments.at(i)->bind_variables_to_parameters(sig); |
|
885 } |
|
886 if (_outer_class != NULL) { |
|
887 _outer_class->bind_variables_to_parameters(sig); |
|
888 } |
|
889 } |
|
890 |
|
891 TypeArgument* ClassType::type_argument_at(int i) { |
|
892 if (i >= 0 && i < _type_arguments.length()) { |
|
893 return _type_arguments.at(i); |
|
894 } else { |
|
895 return NULL; |
|
896 } |
|
897 } |
|
898 |
|
899 #ifndef PRODUCT |
|
900 void ClassType::reify_signature(stringStream* ss, Context* ctx) { |
|
901 ss->print("L"); |
|
902 _identifier->print_on(ss); |
|
903 ss->print(";"); |
|
904 } |
|
905 |
|
906 void ClassType::print_on(outputStream* str) const { |
|
907 str->indent().print_cr("Class {"); |
|
908 { |
|
909 streamIndentor si(str); |
|
910 str->indent().print("Name: "); |
|
911 _identifier->print_on(str); |
|
912 str->print_cr(""); |
|
913 if (_type_arguments.length() != 0) { |
|
914 str->indent().print_cr("Type Arguments: {"); |
|
915 { |
|
916 streamIndentor si(str); |
|
917 for (int j = 0; j < _type_arguments.length(); ++j) { |
|
918 _type_arguments.at(j)->print_on(str); |
|
919 } |
|
920 } |
|
921 str->indent().print_cr("}"); |
|
922 } |
|
923 if (_outer_class != NULL) { |
|
924 str->indent().print_cr("Outer Class: "); |
|
925 streamIndentor sir(str); |
|
926 _outer_class->print_on(str); |
|
927 } |
|
928 } |
|
929 str->indent().print_cr("}"); |
|
930 } |
|
931 #endif // ndef PRODUCT |
|
932 |
|
933 bool ClassType::covariant_match(Type* other, Context* ctx) { |
|
934 |
|
935 if (other == this) { |
|
936 return true; |
|
937 } |
|
938 |
|
939 TypeVariable* variable = other->as_variable(); |
|
940 if (variable != NULL) { |
|
941 other = variable->resolve(ctx, 0); |
|
942 } |
|
943 |
|
944 ClassType* outer = outer_class(); |
|
945 ClassType* other_class = other->as_class(); |
|
946 |
|
947 if (other_class == NULL || |
|
948 (outer == NULL) != (other_class->outer_class() == NULL)) { |
|
949 return false; |
|
950 } |
|
951 |
|
952 if (!_identifier->equals(other_class->_identifier)) { |
|
953 return false; |
|
954 } |
|
955 |
|
956 if (outer != NULL && !outer->covariant_match(other_class->outer_class(), ctx)) { |
|
957 return false; |
|
958 } |
|
959 |
|
960 return true; |
|
961 } |
|
962 |
|
963 ClassType* ClassType::canonicalize(Context* ctx, int ctx_depth) { |
|
964 |
|
965 GrowableArray<TypeArgument*> args(_type_arguments.length()); |
|
966 for (int i = 0; i < _type_arguments.length(); ++i) { |
|
967 args.append(_type_arguments.at(i)->canonicalize(ctx, ctx_depth)); |
|
968 } |
|
969 |
|
970 ClassType* outer = _outer_class == NULL ? NULL : |
|
971 _outer_class->canonicalize(ctx, ctx_depth); |
|
972 |
|
973 return new ClassType(_identifier, args, outer); |
|
974 } |
|
975 |
|
976 TypeVariable* TypeVariable::parse_generic_signature(DescriptorStream* STREAM) { |
|
977 STREAM->set_mark(); |
|
978 char c = READ(); |
|
979 while (c != ';') { |
|
980 c = READ(); |
|
981 } |
|
982 Identifier* id = STREAM->identifier_from_mark(); |
|
983 |
|
984 return new TypeVariable(id); |
|
985 } |
|
986 |
|
987 void TypeVariable::bind_variables_to_parameters(Descriptor* sig) { |
|
988 _parameter = sig->find_type_parameter(_id, &_inner_depth); |
|
989 if (VerifyGenericSignatures && _parameter == NULL) { |
|
990 fatal("Could not find formal parameter"); |
|
991 } |
|
992 } |
|
993 |
|
994 Type* TypeVariable::resolve(Context* ctx, int ctx_depth) { |
|
995 if (parameter() != NULL) { |
|
996 return parameter()->resolve(ctx, inner_depth(), ctx_depth); |
|
997 } else { |
|
998 if (VerifyGenericSignatures) { |
|
999 fatal("Type variable matches no parameter"); |
|
1000 } |
|
1001 return NULL; |
|
1002 } |
|
1003 } |
|
1004 |
|
1005 bool TypeVariable::covariant_match(Type* other, Context* ctx) { |
|
1006 |
|
1007 if (other == this) { |
|
1008 return true; |
|
1009 } |
|
1010 |
|
1011 Context my_context(NULL); // empty, results in erasure |
|
1012 Type* my_type = resolve(&my_context, 0); |
|
1013 if (my_type == NULL) { |
|
1014 return false; |
|
1015 } |
|
1016 |
|
1017 return my_type->covariant_match(other, ctx); |
|
1018 } |
|
1019 |
|
1020 Type* TypeVariable::canonicalize(Context* ctx, int ctx_depth) { |
|
1021 return resolve(ctx, ctx_depth); |
|
1022 } |
|
1023 |
|
1024 #ifndef PRODUCT |
|
1025 void TypeVariable::reify_signature(stringStream* ss, Context* ctx) { |
|
1026 Type* type = resolve(ctx, 0); |
|
1027 if (type != NULL) { |
|
1028 type->reify_signature(ss, ctx); |
|
1029 } |
|
1030 } |
|
1031 |
|
1032 void TypeVariable::print_on(outputStream* str) const { |
|
1033 str->indent().print_cr("Type Variable {"); |
|
1034 { |
|
1035 streamIndentor si(str); |
|
1036 str->indent().print("Name: "); |
|
1037 _id->print_on(str); |
|
1038 str->print_cr(""); |
|
1039 str->indent().print_cr("Inner depth: %d", _inner_depth); |
|
1040 } |
|
1041 str->indent().print_cr("}"); |
|
1042 } |
|
1043 #endif // ndef PRODUCT |
|
1044 |
|
1045 ArrayType* ArrayType::parse_generic_signature(DescriptorStream* STREAM) { |
|
1046 Type* base = Type::parse_generic_signature(CHECK_STREAM); |
|
1047 return new ArrayType(base); |
|
1048 } |
|
1049 |
|
1050 void ArrayType::bind_variables_to_parameters(Descriptor* sig) { |
|
1051 assert(_base != NULL, "Invalid base"); |
|
1052 _base->bind_variables_to_parameters(sig); |
|
1053 } |
|
1054 |
|
1055 bool ArrayType::covariant_match(Type* other, Context* ctx) { |
|
1056 assert(_base != NULL, "Invalid base"); |
|
1057 |
|
1058 if (other == this) { |
|
1059 return true; |
|
1060 } |
|
1061 |
|
1062 ArrayType* other_array = other->as_array(); |
|
1063 return (other_array != NULL && _base->covariant_match(other_array->_base, ctx)); |
|
1064 } |
|
1065 |
|
1066 ArrayType* ArrayType::canonicalize(Context* ctx, int ctx_depth) { |
|
1067 assert(_base != NULL, "Invalid base"); |
|
1068 return new ArrayType(_base->canonicalize(ctx, ctx_depth)); |
|
1069 } |
|
1070 |
|
1071 #ifndef PRODUCT |
|
1072 void ArrayType::reify_signature(stringStream* ss, Context* ctx) { |
|
1073 assert(_base != NULL, "Invalid base"); |
|
1074 ss->print("["); |
|
1075 _base->reify_signature(ss, ctx); |
|
1076 } |
|
1077 |
|
1078 void ArrayType::print_on(outputStream* str) const { |
|
1079 str->indent().print_cr("Array {"); |
|
1080 { |
|
1081 streamIndentor si(str); |
|
1082 _base->print_on(str); |
|
1083 } |
|
1084 str->indent().print_cr("}"); |
|
1085 } |
|
1086 #endif // ndef PRODUCT |
|
1087 |
|
1088 bool PrimitiveType::covariant_match(Type* other, Context* ctx) { |
|
1089 |
|
1090 PrimitiveType* other_prim = other->as_primitive(); |
|
1091 return (other_prim != NULL && _type == other_prim->_type); |
|
1092 } |
|
1093 |
|
1094 PrimitiveType* PrimitiveType::canonicalize(Context* ctx, int ctxd) { |
|
1095 return this; |
|
1096 } |
|
1097 |
|
1098 #ifndef PRODUCT |
|
1099 void PrimitiveType::reify_signature(stringStream* ss, Context* ctx) { |
|
1100 ss->print("%c", _type); |
|
1101 } |
|
1102 |
|
1103 void PrimitiveType::print_on(outputStream* str) const { |
|
1104 str->indent().print_cr("Primitive: '%c'", _type); |
|
1105 } |
|
1106 #endif // ndef PRODUCT |
|
1107 |
|
1108 void PrimitiveType::bind_variables_to_parameters(Descriptor* sig) { |
|
1109 } |
|
1110 |
|
1111 TypeArgument* TypeArgument::parse_generic_signature(DescriptorStream* STREAM) { |
|
1112 char c = READ(); |
|
1113 Type* type = NULL; |
|
1114 |
|
1115 switch (c) { |
|
1116 case '*': |
|
1117 return new TypeArgument(ClassType::java_lang_Object(), NULL); |
|
1118 break; |
|
1119 default: |
|
1120 PUSH(c); |
|
1121 // fall-through |
|
1122 case '+': |
|
1123 case '-': |
|
1124 type = Type::parse_generic_signature(CHECK_STREAM); |
|
1125 if (c == '+') { |
|
1126 return new TypeArgument(type, NULL); |
|
1127 } else if (c == '-') { |
|
1128 return new TypeArgument(ClassType::java_lang_Object(), type); |
|
1129 } else { |
|
1130 return new TypeArgument(type, type); |
|
1131 } |
|
1132 } |
|
1133 } |
|
1134 |
|
1135 void TypeArgument::bind_variables_to_parameters(Descriptor* sig) { |
|
1136 assert(_lower_bound != NULL, "Invalid lower bound"); |
|
1137 _lower_bound->bind_variables_to_parameters(sig); |
|
1138 if (_upper_bound != NULL && _upper_bound != _lower_bound) { |
|
1139 _upper_bound->bind_variables_to_parameters(sig); |
|
1140 } |
|
1141 } |
|
1142 |
|
1143 bool TypeArgument::covariant_match(TypeArgument* other, Context* ctx) { |
|
1144 assert(_lower_bound != NULL, "Invalid lower bound"); |
|
1145 |
|
1146 if (other == this) { |
|
1147 return true; |
|
1148 } |
|
1149 |
|
1150 if (!_lower_bound->covariant_match(other->lower_bound(), ctx)) { |
|
1151 return false; |
|
1152 } |
|
1153 return true; |
|
1154 } |
|
1155 |
|
1156 TypeArgument* TypeArgument::canonicalize(Context* ctx, int ctx_depth) { |
|
1157 assert(_lower_bound != NULL, "Invalid lower bound"); |
|
1158 Type* lower = _lower_bound->canonicalize(ctx, ctx_depth); |
|
1159 Type* upper = NULL; |
|
1160 |
|
1161 if (_upper_bound == _lower_bound) { |
|
1162 upper = lower; |
|
1163 } else if (_upper_bound != NULL) { |
|
1164 upper = _upper_bound->canonicalize(ctx, ctx_depth); |
|
1165 } |
|
1166 |
|
1167 return new TypeArgument(lower, upper); |
|
1168 } |
|
1169 |
|
1170 #ifndef PRODUCT |
|
1171 void TypeArgument::print_on(outputStream* str) const { |
|
1172 str->indent().print_cr("TypeArgument {"); |
|
1173 { |
|
1174 streamIndentor si(str); |
|
1175 if (_lower_bound != NULL) { |
|
1176 str->indent().print("Lower bound: "); |
|
1177 _lower_bound->print_on(str); |
|
1178 } |
|
1179 if (_upper_bound != NULL) { |
|
1180 str->indent().print("Upper bound: "); |
|
1181 _upper_bound->print_on(str); |
|
1182 } |
|
1183 } |
|
1184 str->indent().print_cr("}"); |
|
1185 } |
|
1186 #endif // ndef PRODUCT |
|
1187 |
|
1188 void Context::Mark::destroy() { |
|
1189 if (is_active()) { |
|
1190 _context->reset_to_mark(_marked_size); |
|
1191 } |
|
1192 deactivate(); |
|
1193 } |
|
1194 |
|
1195 void Context::apply_type_arguments( |
|
1196 InstanceKlass* current, InstanceKlass* super, TRAPS) { |
|
1197 assert(_cache != NULL, "Cannot use an empty context"); |
|
1198 ClassType* spec = NULL; |
|
1199 if (current != NULL) { |
|
1200 ClassDescriptor* descriptor = _cache->descriptor_for(current, CHECK); |
|
1201 if (super == current->super()) { |
|
1202 spec = descriptor->super(); |
|
1203 } else { |
|
1204 spec = descriptor->interface_desc(super->name()); |
|
1205 } |
|
1206 if (spec != NULL) { |
|
1207 _type_arguments.push(spec); |
|
1208 } |
|
1209 } |
|
1210 } |
|
1211 |
|
1212 void Context::reset_to_mark(int size) { |
|
1213 _type_arguments.trunc_to(size); |
|
1214 } |
|
1215 |
|
1216 ClassType* Context::at_depth(int i) const { |
|
1217 if (i < _type_arguments.length()) { |
|
1218 return _type_arguments.at(_type_arguments.length() - 1 - i); |
|
1219 } |
|
1220 return NULL; |
|
1221 } |
|
1222 |
|
1223 #ifndef PRODUCT |
|
1224 void Context::print_on(outputStream* str) const { |
|
1225 str->indent().print_cr("Context {"); |
|
1226 for (int i = 0; i < _type_arguments.length(); ++i) { |
|
1227 streamIndentor si(str); |
|
1228 str->indent().print("leval %d: ", i); |
|
1229 ClassType* ct = at_depth(i); |
|
1230 if (ct == NULL) { |
|
1231 str->print_cr("<empty>"); |
|
1232 continue; |
|
1233 } else { |
|
1234 str->print_cr("{"); |
|
1235 } |
|
1236 |
|
1237 for (int j = 0; j < ct->type_arguments_length(); ++j) { |
|
1238 streamIndentor si(str); |
|
1239 TypeArgument* ta = ct->type_argument_at(j); |
|
1240 Type* bound = ta->lower_bound(); |
|
1241 bound->print_on(str); |
|
1242 } |
|
1243 str->indent().print_cr("}"); |
|
1244 } |
|
1245 str->indent().print_cr("}"); |
|
1246 } |
|
1247 #endif // ndef PRODUCT |
|
1248 |
|
1249 ClassDescriptor* DescriptorCache::descriptor_for(InstanceKlass* ik, TRAPS) { |
|
1250 |
|
1251 ClassDescriptor** existing = _class_descriptors.get(ik); |
|
1252 if (existing == NULL) { |
|
1253 ClassDescriptor* cd = ClassDescriptor::parse_generic_signature(ik, CHECK_NULL); |
|
1254 _class_descriptors.put(ik, cd); |
|
1255 return cd; |
|
1256 } else { |
|
1257 return *existing; |
|
1258 } |
|
1259 } |
|
1260 |
|
1261 MethodDescriptor* DescriptorCache::descriptor_for( |
|
1262 Method* mh, ClassDescriptor* cd, TRAPS) { |
|
1263 assert(mh != NULL && cd != NULL, "Should not be NULL"); |
|
1264 MethodDescriptor** existing = _method_descriptors.get(mh); |
|
1265 if (existing == NULL) { |
|
1266 MethodDescriptor* md = MethodDescriptor::parse_generic_signature(mh, cd); |
|
1267 _method_descriptors.put(mh, md); |
|
1268 return md; |
|
1269 } else { |
|
1270 return *existing; |
|
1271 } |
|
1272 } |
|
1273 MethodDescriptor* DescriptorCache::descriptor_for(Method* mh, TRAPS) { |
|
1274 ClassDescriptor* cd = descriptor_for( |
|
1275 InstanceKlass::cast(mh->method_holder()), CHECK_NULL); |
|
1276 return descriptor_for(mh, cd, THREAD); |
|
1277 } |
|
1278 |
|
1279 } // namespace generic |
|