/* * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ #include "precompiled.hpp" #include "classfile/genericSignatures.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" #include "memory/resourceArea.hpp" namespace generic { // Helper class for parsing the generic signature Symbol in klass and methods class DescriptorStream : public ResourceObj { private: Symbol* _symbol; int _offset; int _mark; const char* _parse_error; void set_parse_error(const char* error) { assert(error != NULL, "Can't set NULL error string"); _parse_error = error; } public: DescriptorStream(Symbol* sym) : _symbol(sym), _offset(0), _mark(-1), _parse_error(NULL) {} const char* parse_error() const { return _parse_error; } bool at_end() { return _offset >= _symbol->utf8_length(); } char peek() { if (at_end()) { set_parse_error("Peeking past end of signature"); return '\0'; } else { return _symbol->byte_at(_offset); } } char read() { if (at_end()) { set_parse_error("Reading past end of signature"); return '\0'; } else { return _symbol->byte_at(_offset++); } } void read(char expected) { char c = read(); assert_char(c, expected, 0); } void assert_char(char c, char expected, int pos = -1) { if (c != expected) { const char* fmt = "Parse error at %d: expected %c but got %c"; size_t len = strlen(fmt) + 5; char* buffer = NEW_RESOURCE_ARRAY(char, len); jio_snprintf(buffer, len, fmt, _offset + pos, expected, c); set_parse_error(buffer); } } void push(char c) { assert(c == _symbol->byte_at(_offset - 1), "Pushing back wrong value"); --_offset; } void expect_end() { if (!at_end()) { set_parse_error("Unexpected data trailing signature"); } } bool has_mark() { return _mark != -1; } void set_mark() { _mark = _offset; } Identifier* identifier_from_mark() { assert(has_mark(), "Mark should be set"); if (!has_mark()) { set_parse_error("Expected mark to be set"); return NULL; } else { Identifier* id = new Identifier(_symbol, _mark, _offset - 1); _mark = -1; return id; } } }; #define CHECK_FOR_PARSE_ERROR() \ if (STREAM->parse_error() != NULL) { \ if (VerifyGenericSignatures) { \ fatal(STREAM->parse_error()); \ } \ return NULL; \ } 0 #define READ() STREAM->read(); CHECK_FOR_PARSE_ERROR() #define PEEK() STREAM->peek(); CHECK_FOR_PARSE_ERROR() #define PUSH(c) STREAM->push(c) #define EXPECT(c) STREAM->read(c); CHECK_FOR_PARSE_ERROR() #define EXPECTED(c, ch) STREAM->assert_char(c, ch); CHECK_FOR_PARSE_ERROR() #define EXPECT_END() STREAM->expect_end(); CHECK_FOR_PARSE_ERROR() #define CHECK_STREAM STREAM); CHECK_FOR_PARSE_ERROR(); (0 #ifndef PRODUCT void Identifier::print_on(outputStream* str) const { for (int i = _begin; i < _end; ++i) { str->print("%c", (char)_sym->byte_at(i)); } } #endif // ndef PRODUCT bool Identifier::equals(Identifier* other) { if (_sym == other->_sym && _begin == other->_begin && _end == other->_end) { return true; } else if (_end - _begin != other->_end - other->_begin) { return false; } else { size_t len = _end - _begin; char* addr = ((char*)_sym->bytes()) + _begin; char* oaddr = ((char*)other->_sym->bytes()) + other->_begin; return strncmp(addr, oaddr, len) == 0; } } bool Identifier::equals(Symbol* sym) { Identifier id(sym, 0, sym->utf8_length()); return equals(&id); } /** * A formal type parameter may be found in the the enclosing class, but it could * also come from an enclosing method or outer class, in the case of inner-outer * classes or anonymous classes. For example: * * class Outer { * class Inner { * void m(T t, V v, W w); * } * } * * In this case, the type variables in m()'s signature are not all found in the * immediate enclosing class (Inner). class Inner has only type parameter W, * but it's outer_class field will reference Outer's descriptor which contains * T & V (no outer_method in this case). * * If you have an anonymous class, it has both an enclosing method *and* an * enclosing class where type parameters can be declared: * * class MOuter { * void bar(V v) { * Runnable r = new Runnable() { * public void run() {} * public void foo(T t, V v) { ... } * }; * } * } * * In this case, foo will be a member of some class, Runnable$1, which has no * formal parameters itself, but has an outer_method (bar()) which provides * type parameter V, and an outer class MOuter with type parameter T. * * It is also possible that the outer class is itself an inner class to some * other class (or an anonymous class with an enclosing method), so we need to * follow the outer_class/outer_method chain to it's end when looking for a * type parameter. */ TypeParameter* Descriptor::find_type_parameter(Identifier* id, int* depth) { int current_depth = 0; MethodDescriptor* outer_method = as_method_signature(); ClassDescriptor* outer_class = as_class_signature(); if (outer_class == NULL) { // 'this' is a method signature; use the holder outer_class = outer_method->outer_class(); } while (outer_method != NULL || outer_class != NULL) { if (outer_method != NULL) { for (int i = 0; i < outer_method->type_parameters().length(); ++i) { TypeParameter* p = outer_method->type_parameters().at(i); if (p->identifier()->equals(id)) { *depth = -1; // indicates this this is a method parameter return p; } } } if (outer_class != NULL) { for (int i = 0; i < outer_class->type_parameters().length(); ++i) { TypeParameter* p = outer_class->type_parameters().at(i); if (p->identifier()->equals(id)) { *depth = current_depth; return p; } } outer_method = outer_class->outer_method(); outer_class = outer_class->outer_class(); ++current_depth; } } if (VerifyGenericSignatures) { fatal("Could not resolve identifier"); } return NULL; } ClassDescriptor* ClassDescriptor::parse_generic_signature(Klass* klass, TRAPS) { return parse_generic_signature(klass, NULL, CHECK_NULL); } ClassDescriptor* ClassDescriptor::parse_generic_signature( Klass* klass, Symbol* original_name, TRAPS) { InstanceKlass* ik = InstanceKlass::cast(klass); Symbol* sym = ik->generic_signature(); ClassDescriptor* spec; if (sym == NULL || (spec = ClassDescriptor::parse_generic_signature(sym)) == NULL) { spec = ClassDescriptor::placeholder(ik); } u2 outer_index = get_outer_class_index(ik, CHECK_NULL); if (outer_index != 0) { if (original_name == NULL) { original_name = ik->name(); } Handle class_loader = Handle(THREAD, ik->class_loader()); Handle protection_domain = Handle(THREAD, ik->protection_domain()); Symbol* outer_name = ik->constants()->klass_name_at(outer_index); Klass* outer = SystemDictionary::find( outer_name, class_loader, protection_domain, CHECK_NULL); if (outer == NULL && !THREAD->is_Compiler_thread()) { outer = SystemDictionary::resolve_super_or_fail(original_name, outer_name, class_loader, protection_domain, false, CHECK_NULL); } InstanceKlass* outer_ik; ClassDescriptor* outer_spec = NULL; if (outer == NULL) { outer_spec = ClassDescriptor::placeholder(ik); assert(false, "Outer class not loaded and not loadable from here"); } else { outer_ik = InstanceKlass::cast(outer); outer_spec = parse_generic_signature(outer, original_name, CHECK_NULL); } spec->set_outer_class(outer_spec); u2 encl_method_idx = ik->enclosing_method_method_index(); if (encl_method_idx != 0 && outer_ik != NULL) { ConstantPool* cp = ik->constants(); u2 name_index = cp->name_ref_index_at(encl_method_idx); u2 sig_index = cp->signature_ref_index_at(encl_method_idx); Symbol* name = cp->symbol_at(name_index); Symbol* sig = cp->symbol_at(sig_index); Method* m = outer_ik->find_method(name, sig); if (m != NULL) { Symbol* gsig = m->generic_signature(); if (gsig != NULL) { MethodDescriptor* gms = MethodDescriptor::parse_generic_signature(gsig, outer_spec); spec->set_outer_method(gms); } } else if (VerifyGenericSignatures) { ResourceMark rm; stringStream ss; ss.print("Could not find method %s %s in class %s", name->as_C_string(), sig->as_C_string(), outer_name->as_C_string()); fatal(ss.as_string()); } } } spec->bind_variables_to_parameters(); return spec; } ClassDescriptor* ClassDescriptor::placeholder(InstanceKlass* klass) { GrowableArray formals; GrowableArray interfaces; ClassType* super_type = NULL; Klass* super_klass = klass->super(); if (super_klass != NULL) { InstanceKlass* super = InstanceKlass::cast(super_klass); super_type = ClassType::from_symbol(super->name()); } for (int i = 0; i < klass->local_interfaces()->length(); ++i) { InstanceKlass* iface = InstanceKlass::cast(klass->local_interfaces()->at(i)); interfaces.append(ClassType::from_symbol(iface->name())); } return new ClassDescriptor(formals, super_type, interfaces); } ClassDescriptor* ClassDescriptor::parse_generic_signature(Symbol* sym) { DescriptorStream ds(sym); DescriptorStream* STREAM = &ds; GrowableArray parameters(8); char c = READ(); if (c == '<') { c = READ(); while (c != '>') { PUSH(c); TypeParameter* ftp = TypeParameter::parse_generic_signature(CHECK_STREAM); parameters.append(ftp); c = READ(); } } else { PUSH(c); } EXPECT('L'); ClassType* super = ClassType::parse_generic_signature(CHECK_STREAM); GrowableArray signatures(2); while (!STREAM->at_end()) { EXPECT('L'); ClassType* iface = ClassType::parse_generic_signature(CHECK_STREAM); signatures.append(iface); } EXPECT_END(); return new ClassDescriptor(parameters, super, signatures); } #ifndef PRODUCT void ClassDescriptor::print_on(outputStream* str) const { str->indent().print_cr("ClassDescriptor {"); { streamIndentor si(str); if (_type_parameters.length() > 0) { str->indent().print_cr("Formals {"); { streamIndentor si(str); for (int i = 0; i < _type_parameters.length(); ++i) { _type_parameters.at(i)->print_on(str); } } str->indent().print_cr("}"); } if (_super != NULL) { str->indent().print_cr("Superclass: "); { streamIndentor si(str); _super->print_on(str); } } if (_interfaces.length() > 0) { str->indent().print_cr("SuperInterfaces: {"); { streamIndentor si(str); for (int i = 0; i < _interfaces.length(); ++i) { _interfaces.at(i)->print_on(str); } } str->indent().print_cr("}"); } if (_outer_method != NULL) { str->indent().print_cr("Outer Method: {"); { streamIndentor si(str); _outer_method->print_on(str); } str->indent().print_cr("}"); } if (_outer_class != NULL) { str->indent().print_cr("Outer Class: {"); { streamIndentor si(str); _outer_class->print_on(str); } str->indent().print_cr("}"); } } str->indent().print_cr("}"); } #endif // ndef PRODUCT ClassType* ClassDescriptor::interface_desc(Symbol* sym) { for (int i = 0; i < _interfaces.length(); ++i) { if (_interfaces.at(i)->identifier()->equals(sym)) { return _interfaces.at(i); } } if (VerifyGenericSignatures) { fatal("Did not find expected interface"); } return NULL; } void ClassDescriptor::bind_variables_to_parameters() { if (_outer_class != NULL) { _outer_class->bind_variables_to_parameters(); } if (_outer_method != NULL) { _outer_method->bind_variables_to_parameters(); } for (int i = 0; i < _type_parameters.length(); ++i) { _type_parameters.at(i)->bind_variables_to_parameters(this, i); } if (_super != NULL) { _super->bind_variables_to_parameters(this); } for (int i = 0; i < _interfaces.length(); ++i) { _interfaces.at(i)->bind_variables_to_parameters(this); } } ClassDescriptor* ClassDescriptor::canonicalize(Context* ctx) { GrowableArray type_params(_type_parameters.length()); for (int i = 0; i < _type_parameters.length(); ++i) { type_params.append(_type_parameters.at(i)->canonicalize(ctx, 0)); } ClassDescriptor* outer = _outer_class == NULL ? NULL : _outer_class->canonicalize(ctx); ClassType* super = _super == NULL ? NULL : _super->canonicalize(ctx, 0); GrowableArray interfaces(_interfaces.length()); for (int i = 0; i < _interfaces.length(); ++i) { interfaces.append(_interfaces.at(i)->canonicalize(ctx, 0)); } MethodDescriptor* md = _outer_method == NULL ? NULL : _outer_method->canonicalize(ctx); return new ClassDescriptor(type_params, super, interfaces, outer, md); } u2 ClassDescriptor::get_outer_class_index(InstanceKlass* klass, TRAPS) { int inner_index = InstanceKlass::inner_class_inner_class_info_offset; int outer_index = InstanceKlass::inner_class_outer_class_info_offset; int name_offset = InstanceKlass::inner_class_inner_name_offset; int next_offset = InstanceKlass::inner_class_next_offset; if (klass->inner_classes() == NULL || klass->inner_classes()->length() == 0) { // No inner class info => no declaring class return 0; } Array* i_icls = klass->inner_classes(); ConstantPool* i_cp = klass->constants(); int i_length = i_icls->length(); // Find inner_klass attribute for (int i = 0; i + next_offset < i_length; i += next_offset) { u2 ioff = i_icls->at(i + inner_index); u2 ooff = i_icls->at(i + outer_index); u2 noff = i_icls->at(i + name_offset); if (ioff != 0) { // Check to see if the name matches the class we're looking for // before attempting to find the class. if (i_cp->klass_name_at_matches(klass, ioff) && ooff != 0) { return ooff; } } } // It may be anonymous; try for that. u2 encl_method_class_idx = klass->enclosing_method_class_index(); if (encl_method_class_idx != 0) { return encl_method_class_idx; } return 0; } MethodDescriptor* MethodDescriptor::parse_generic_signature(Method* m, ClassDescriptor* outer) { Symbol* generic_sig = m->generic_signature(); MethodDescriptor* md = NULL; if (generic_sig == NULL || (md = parse_generic_signature(generic_sig, outer)) == NULL) { md = parse_generic_signature(m->signature(), outer); } assert(md != NULL, "Could not parse method signature"); md->bind_variables_to_parameters(); return md; } MethodDescriptor* MethodDescriptor::parse_generic_signature(Symbol* sym, ClassDescriptor* outer) { DescriptorStream ds(sym); DescriptorStream* STREAM = &ds; GrowableArray params(8); char c = READ(); if (c == '<') { c = READ(); while (c != '>') { PUSH(c); TypeParameter* ftp = TypeParameter::parse_generic_signature(CHECK_STREAM); params.append(ftp); c = READ(); } } else { PUSH(c); } EXPECT('('); GrowableArray parameters(8); c = READ(); while (c != ')') { PUSH(c); Type* arg = Type::parse_generic_signature(CHECK_STREAM); parameters.append(arg); c = READ(); } Type* rt = Type::parse_generic_signature(CHECK_STREAM); GrowableArray throws; while (!STREAM->at_end()) { EXPECT('^'); Type* spec = Type::parse_generic_signature(CHECK_STREAM); throws.append(spec); } return new MethodDescriptor(params, outer, parameters, rt, throws); } void MethodDescriptor::bind_variables_to_parameters() { for (int i = 0; i < _type_parameters.length(); ++i) { _type_parameters.at(i)->bind_variables_to_parameters(this, i); } for (int i = 0; i < _parameters.length(); ++i) { _parameters.at(i)->bind_variables_to_parameters(this); } _return_type->bind_variables_to_parameters(this); for (int i = 0; i < _throws.length(); ++i) { _throws.at(i)->bind_variables_to_parameters(this); } } bool MethodDescriptor::covariant_match(MethodDescriptor* other, Context* ctx) { if (_parameters.length() == other->_parameters.length()) { for (int i = 0; i < _parameters.length(); ++i) { if (!_parameters.at(i)->covariant_match(other->_parameters.at(i), ctx)) { return false; } } if (_return_type->as_primitive() != NULL) { return _return_type->covariant_match(other->_return_type, ctx); } else { // return type is a reference return other->_return_type->as_class() != NULL || other->_return_type->as_variable() != NULL || other->_return_type->as_array() != NULL; } } else { return false; } } MethodDescriptor* MethodDescriptor::canonicalize(Context* ctx) { GrowableArray type_params(_type_parameters.length()); for (int i = 0; i < _type_parameters.length(); ++i) { type_params.append(_type_parameters.at(i)->canonicalize(ctx, 0)); } ClassDescriptor* outer = _outer_class == NULL ? NULL : _outer_class->canonicalize(ctx); GrowableArray params(_parameters.length()); for (int i = 0; i < _parameters.length(); ++i) { params.append(_parameters.at(i)->canonicalize(ctx, 0)); } Type* rt = _return_type->canonicalize(ctx, 0); GrowableArray throws(_throws.length()); for (int i = 0; i < _throws.length(); ++i) { throws.append(_throws.at(i)->canonicalize(ctx, 0)); } return new MethodDescriptor(type_params, outer, params, rt, throws); } #ifndef PRODUCT TempNewSymbol MethodDescriptor::reify_signature(Context* ctx, TRAPS) { stringStream ss(256); ss.print("("); for (int i = 0; i < _parameters.length(); ++i) { _parameters.at(i)->reify_signature(&ss, ctx); } ss.print(")"); _return_type->reify_signature(&ss, ctx); return SymbolTable::new_symbol(ss.base(), (int)ss.size(), THREAD); } void MethodDescriptor::print_on(outputStream* str) const { str->indent().print_cr("MethodDescriptor {"); { streamIndentor si(str); if (_type_parameters.length() > 0) { str->indent().print_cr("Formals: {"); { streamIndentor si(str); for (int i = 0; i < _type_parameters.length(); ++i) { _type_parameters.at(i)->print_on(str); } } str->indent().print_cr("}"); } str->indent().print_cr("Parameters: {"); { streamIndentor si(str); for (int i = 0; i < _parameters.length(); ++i) { _parameters.at(i)->print_on(str); } } str->indent().print_cr("}"); str->indent().print_cr("Return Type: "); { streamIndentor si(str); _return_type->print_on(str); } if (_throws.length() > 0) { str->indent().print_cr("Throws: {"); { streamIndentor si(str); for (int i = 0; i < _throws.length(); ++i) { _throws.at(i)->print_on(str); } } str->indent().print_cr("}"); } } str->indent().print_cr("}"); } #endif // ndef PRODUCT TypeParameter* TypeParameter::parse_generic_signature(DescriptorStream* STREAM) { STREAM->set_mark(); char c = READ(); while (c != ':') { c = READ(); } Identifier* id = STREAM->identifier_from_mark(); ClassType* class_bound = NULL; GrowableArray interface_bounds(8); c = READ(); if (c != '>') { if (c != ':') { EXPECTED(c, 'L'); class_bound = ClassType::parse_generic_signature(CHECK_STREAM); c = READ(); } while (c == ':') { EXPECT('L'); ClassType* fts = ClassType::parse_generic_signature(CHECK_STREAM); interface_bounds.append(fts); c = READ(); } } PUSH(c); return new TypeParameter(id, class_bound, interface_bounds); } void TypeParameter::bind_variables_to_parameters(Descriptor* sig, int position) { if (_class_bound != NULL) { _class_bound->bind_variables_to_parameters(sig); } for (int i = 0; i < _interface_bounds.length(); ++i) { _interface_bounds.at(i)->bind_variables_to_parameters(sig); } _position = position; } Type* TypeParameter::resolve( Context* ctx, int inner_depth, int ctx_depth) { if (inner_depth == -1) { // This indicates that the parameter is a method type parameter, which // isn't resolveable using the class hierarchy context return bound(); } ClassType* provider = ctx->at_depth(ctx_depth); if (provider != NULL) { for (int i = 0; i < inner_depth && provider != NULL; ++i) { provider = provider->outer_class(); } if (provider != NULL) { TypeArgument* arg = provider->type_argument_at(_position); if (arg != NULL) { Type* value = arg->lower_bound(); return value->canonicalize(ctx, ctx_depth + 1); } } } return bound(); } TypeParameter* TypeParameter::canonicalize(Context* ctx, int ctx_depth) { ClassType* bound = _class_bound == NULL ? NULL : _class_bound->canonicalize(ctx, ctx_depth); GrowableArray ifaces(_interface_bounds.length()); for (int i = 0; i < _interface_bounds.length(); ++i) { ifaces.append(_interface_bounds.at(i)->canonicalize(ctx, ctx_depth)); } TypeParameter* ret = new TypeParameter(_identifier, bound, ifaces); ret->_position = _position; return ret; } ClassType* TypeParameter::bound() { if (_class_bound != NULL) { return _class_bound; } if (_interface_bounds.length() == 1) { return _interface_bounds.at(0); } return ClassType::java_lang_Object(); // TODO: investigate this case } #ifndef PRODUCT void TypeParameter::print_on(outputStream* str) const { str->indent().print_cr("Formal: {"); { streamIndentor si(str); str->indent().print("Identifier: "); _identifier->print_on(str); str->print_cr(""); if (_class_bound != NULL) { str->indent().print_cr("Class Bound: "); streamIndentor si(str); _class_bound->print_on(str); } if (_interface_bounds.length() > 0) { str->indent().print_cr("Interface Bounds: {"); { streamIndentor si(str); for (int i = 0; i < _interface_bounds.length(); ++i) { _interface_bounds.at(i)->print_on(str); } } str->indent().print_cr("}"); } str->indent().print_cr("Ordinal Position: %d", _position); } str->indent().print_cr("}"); } #endif // ndef PRODUCT Type* Type::parse_generic_signature(DescriptorStream* STREAM) { char c = READ(); switch (c) { case 'L': return ClassType::parse_generic_signature(CHECK_STREAM); case 'T': return TypeVariable::parse_generic_signature(CHECK_STREAM); case '[': return ArrayType::parse_generic_signature(CHECK_STREAM); default: return new PrimitiveType(c); } } Identifier* ClassType::parse_generic_signature_simple(GrowableArray* args, bool* has_inner, DescriptorStream* STREAM) { STREAM->set_mark(); char c = READ(); while (c != ';' && c != '.' && c != '<') { c = READ(); } Identifier* id = STREAM->identifier_from_mark(); if (c == '<') { c = READ(); while (c != '>') { PUSH(c); TypeArgument* arg = TypeArgument::parse_generic_signature(CHECK_STREAM); args->append(arg); c = READ(); } c = READ(); } *has_inner = (c == '.'); if (!(*has_inner)) { EXPECTED(c, ';'); } return id; } ClassType* ClassType::parse_generic_signature(DescriptorStream* STREAM) { return parse_generic_signature(NULL, CHECK_STREAM); } ClassType* ClassType::parse_generic_signature(ClassType* outer, DescriptorStream* STREAM) { GrowableArray args; ClassType* gct = NULL; bool has_inner = false; Identifier* id = parse_generic_signature_simple(&args, &has_inner, STREAM); if (id != NULL) { gct = new ClassType(id, args, outer); if (has_inner) { gct = parse_generic_signature(gct, CHECK_STREAM); } } return gct; } ClassType* ClassType::from_symbol(Symbol* sym) { assert(sym != NULL, "Must not be null"); GrowableArray args; Identifier* id = new Identifier(sym, 0, sym->utf8_length()); return new ClassType(id, args, NULL); } ClassType* ClassType::java_lang_Object() { return from_symbol(vmSymbols::java_lang_Object()); } void ClassType::bind_variables_to_parameters(Descriptor* sig) { for (int i = 0; i < _type_arguments.length(); ++i) { _type_arguments.at(i)->bind_variables_to_parameters(sig); } if (_outer_class != NULL) { _outer_class->bind_variables_to_parameters(sig); } } TypeArgument* ClassType::type_argument_at(int i) { if (i >= 0 && i < _type_arguments.length()) { return _type_arguments.at(i); } else { return NULL; } } #ifndef PRODUCT void ClassType::reify_signature(stringStream* ss, Context* ctx) { ss->print("L"); _identifier->print_on(ss); ss->print(";"); } void ClassType::print_on(outputStream* str) const { str->indent().print_cr("Class {"); { streamIndentor si(str); str->indent().print("Name: "); _identifier->print_on(str); str->print_cr(""); if (_type_arguments.length() != 0) { str->indent().print_cr("Type Arguments: {"); { streamIndentor si(str); for (int j = 0; j < _type_arguments.length(); ++j) { _type_arguments.at(j)->print_on(str); } } str->indent().print_cr("}"); } if (_outer_class != NULL) { str->indent().print_cr("Outer Class: "); streamIndentor sir(str); _outer_class->print_on(str); } } str->indent().print_cr("}"); } #endif // ndef PRODUCT bool ClassType::covariant_match(Type* other, Context* ctx) { if (other == this) { return true; } TypeVariable* variable = other->as_variable(); if (variable != NULL) { other = variable->resolve(ctx, 0); } ClassType* outer = outer_class(); ClassType* other_class = other->as_class(); if (other_class == NULL || (outer == NULL) != (other_class->outer_class() == NULL)) { return false; } if (!_identifier->equals(other_class->_identifier)) { return false; } if (outer != NULL && !outer->covariant_match(other_class->outer_class(), ctx)) { return false; } return true; } ClassType* ClassType::canonicalize(Context* ctx, int ctx_depth) { GrowableArray args(_type_arguments.length()); for (int i = 0; i < _type_arguments.length(); ++i) { args.append(_type_arguments.at(i)->canonicalize(ctx, ctx_depth)); } ClassType* outer = _outer_class == NULL ? NULL : _outer_class->canonicalize(ctx, ctx_depth); return new ClassType(_identifier, args, outer); } TypeVariable* TypeVariable::parse_generic_signature(DescriptorStream* STREAM) { STREAM->set_mark(); char c = READ(); while (c != ';') { c = READ(); } Identifier* id = STREAM->identifier_from_mark(); return new TypeVariable(id); } void TypeVariable::bind_variables_to_parameters(Descriptor* sig) { _parameter = sig->find_type_parameter(_id, &_inner_depth); if (VerifyGenericSignatures && _parameter == NULL) { fatal("Could not find formal parameter"); } } Type* TypeVariable::resolve(Context* ctx, int ctx_depth) { if (parameter() != NULL) { return parameter()->resolve(ctx, inner_depth(), ctx_depth); } else { if (VerifyGenericSignatures) { fatal("Type variable matches no parameter"); } return NULL; } } bool TypeVariable::covariant_match(Type* other, Context* ctx) { if (other == this) { return true; } Context my_context(NULL); // empty, results in erasure Type* my_type = resolve(&my_context, 0); if (my_type == NULL) { return false; } return my_type->covariant_match(other, ctx); } Type* TypeVariable::canonicalize(Context* ctx, int ctx_depth) { return resolve(ctx, ctx_depth); } #ifndef PRODUCT void TypeVariable::reify_signature(stringStream* ss, Context* ctx) { Type* type = resolve(ctx, 0); if (type != NULL) { type->reify_signature(ss, ctx); } } void TypeVariable::print_on(outputStream* str) const { str->indent().print_cr("Type Variable {"); { streamIndentor si(str); str->indent().print("Name: "); _id->print_on(str); str->print_cr(""); str->indent().print_cr("Inner depth: %d", _inner_depth); } str->indent().print_cr("}"); } #endif // ndef PRODUCT ArrayType* ArrayType::parse_generic_signature(DescriptorStream* STREAM) { Type* base = Type::parse_generic_signature(CHECK_STREAM); return new ArrayType(base); } void ArrayType::bind_variables_to_parameters(Descriptor* sig) { assert(_base != NULL, "Invalid base"); _base->bind_variables_to_parameters(sig); } bool ArrayType::covariant_match(Type* other, Context* ctx) { assert(_base != NULL, "Invalid base"); if (other == this) { return true; } ArrayType* other_array = other->as_array(); return (other_array != NULL && _base->covariant_match(other_array->_base, ctx)); } ArrayType* ArrayType::canonicalize(Context* ctx, int ctx_depth) { assert(_base != NULL, "Invalid base"); return new ArrayType(_base->canonicalize(ctx, ctx_depth)); } #ifndef PRODUCT void ArrayType::reify_signature(stringStream* ss, Context* ctx) { assert(_base != NULL, "Invalid base"); ss->print("["); _base->reify_signature(ss, ctx); } void ArrayType::print_on(outputStream* str) const { str->indent().print_cr("Array {"); { streamIndentor si(str); _base->print_on(str); } str->indent().print_cr("}"); } #endif // ndef PRODUCT bool PrimitiveType::covariant_match(Type* other, Context* ctx) { PrimitiveType* other_prim = other->as_primitive(); return (other_prim != NULL && _type == other_prim->_type); } PrimitiveType* PrimitiveType::canonicalize(Context* ctx, int ctxd) { return this; } #ifndef PRODUCT void PrimitiveType::reify_signature(stringStream* ss, Context* ctx) { ss->print("%c", _type); } void PrimitiveType::print_on(outputStream* str) const { str->indent().print_cr("Primitive: '%c'", _type); } #endif // ndef PRODUCT void PrimitiveType::bind_variables_to_parameters(Descriptor* sig) { } TypeArgument* TypeArgument::parse_generic_signature(DescriptorStream* STREAM) { char c = READ(); Type* type = NULL; switch (c) { case '*': return new TypeArgument(ClassType::java_lang_Object(), NULL); break; default: PUSH(c); // fall-through case '+': case '-': type = Type::parse_generic_signature(CHECK_STREAM); if (c == '+') { return new TypeArgument(type, NULL); } else if (c == '-') { return new TypeArgument(ClassType::java_lang_Object(), type); } else { return new TypeArgument(type, type); } } } void TypeArgument::bind_variables_to_parameters(Descriptor* sig) { assert(_lower_bound != NULL, "Invalid lower bound"); _lower_bound->bind_variables_to_parameters(sig); if (_upper_bound != NULL && _upper_bound != _lower_bound) { _upper_bound->bind_variables_to_parameters(sig); } } bool TypeArgument::covariant_match(TypeArgument* other, Context* ctx) { assert(_lower_bound != NULL, "Invalid lower bound"); if (other == this) { return true; } if (!_lower_bound->covariant_match(other->lower_bound(), ctx)) { return false; } return true; } TypeArgument* TypeArgument::canonicalize(Context* ctx, int ctx_depth) { assert(_lower_bound != NULL, "Invalid lower bound"); Type* lower = _lower_bound->canonicalize(ctx, ctx_depth); Type* upper = NULL; if (_upper_bound == _lower_bound) { upper = lower; } else if (_upper_bound != NULL) { upper = _upper_bound->canonicalize(ctx, ctx_depth); } return new TypeArgument(lower, upper); } #ifndef PRODUCT void TypeArgument::print_on(outputStream* str) const { str->indent().print_cr("TypeArgument {"); { streamIndentor si(str); if (_lower_bound != NULL) { str->indent().print("Lower bound: "); _lower_bound->print_on(str); } if (_upper_bound != NULL) { str->indent().print("Upper bound: "); _upper_bound->print_on(str); } } str->indent().print_cr("}"); } #endif // ndef PRODUCT void Context::Mark::destroy() { if (is_active()) { _context->reset_to_mark(_marked_size); } deactivate(); } void Context::apply_type_arguments( InstanceKlass* current, InstanceKlass* super, TRAPS) { assert(_cache != NULL, "Cannot use an empty context"); ClassType* spec = NULL; if (current != NULL) { ClassDescriptor* descriptor = _cache->descriptor_for(current, CHECK); if (super == current->super()) { spec = descriptor->super(); } else { spec = descriptor->interface_desc(super->name()); } if (spec != NULL) { _type_arguments.push(spec); } } } void Context::reset_to_mark(int size) { _type_arguments.trunc_to(size); } ClassType* Context::at_depth(int i) const { if (i < _type_arguments.length()) { return _type_arguments.at(_type_arguments.length() - 1 - i); } return NULL; } #ifndef PRODUCT void Context::print_on(outputStream* str) const { str->indent().print_cr("Context {"); for (int i = 0; i < _type_arguments.length(); ++i) { streamIndentor si(str); str->indent().print("leval %d: ", i); ClassType* ct = at_depth(i); if (ct == NULL) { str->print_cr(""); continue; } else { str->print_cr("{"); } for (int j = 0; j < ct->type_arguments_length(); ++j) { streamIndentor si(str); TypeArgument* ta = ct->type_argument_at(j); Type* bound = ta->lower_bound(); bound->print_on(str); } str->indent().print_cr("}"); } str->indent().print_cr("}"); } #endif // ndef PRODUCT ClassDescriptor* DescriptorCache::descriptor_for(InstanceKlass* ik, TRAPS) { ClassDescriptor** existing = _class_descriptors.get(ik); if (existing == NULL) { ClassDescriptor* cd = ClassDescriptor::parse_generic_signature(ik, CHECK_NULL); _class_descriptors.put(ik, cd); return cd; } else { return *existing; } } MethodDescriptor* DescriptorCache::descriptor_for( Method* mh, ClassDescriptor* cd, TRAPS) { assert(mh != NULL && cd != NULL, "Should not be NULL"); MethodDescriptor** existing = _method_descriptors.get(mh); if (existing == NULL) { MethodDescriptor* md = MethodDescriptor::parse_generic_signature(mh, cd); _method_descriptors.put(mh, md); return md; } else { return *existing; } } MethodDescriptor* DescriptorCache::descriptor_for(Method* mh, TRAPS) { ClassDescriptor* cd = descriptor_for( InstanceKlass::cast(mh->method_holder()), CHECK_NULL); return descriptor_for(mh, cd, THREAD); } } // namespace generic