kamg@4245: /* kamg@4245: * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. kamg@4245: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. kamg@4245: * kamg@4245: * This code is free software; you can redistribute it and/or modify it kamg@4245: * under the terms of the GNU General Public License version 2 only, as kamg@4245: * published by the Free Software Foundation. kamg@4245: * kamg@4245: * This code is distributed in the hope that it will be useful, but WITHOUT kamg@4245: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or kamg@4245: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License kamg@4245: * version 2 for more details (a copy is included in the LICENSE file that kamg@4245: * accompanied this code). kamg@4245: * kamg@4245: * You should have received a copy of the GNU General Public License version kamg@4245: * 2 along with this work; if not, write to the Free Software Foundation, kamg@4245: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. kamg@4245: * kamg@4245: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA kamg@4245: * or visit www.oracle.com if you need additional information or have any kamg@4245: * questions. kamg@4245: * kamg@4245: */ kamg@4245: kamg@4245: #ifndef SHARE_VM_CLASSFILE_GENERICSIGNATURES_HPP kamg@4245: #define SHARE_VM_CLASSFILE_GENERICSIGNATURES_HPP kamg@4245: kamg@4245: #include "classfile/symbolTable.hpp" kamg@4245: #include "memory/allocation.hpp" kamg@4245: #include "runtime/signature.hpp" kamg@4245: #include "utilities/growableArray.hpp" kamg@4245: #include "utilities/resourceHash.hpp" kamg@4245: kamg@4245: class stringStream; kamg@4245: kamg@4245: namespace generic { kamg@4245: kamg@4245: class Identifier; kamg@4245: class ClassDescriptor; kamg@4245: class MethodDescriptor; kamg@4245: kamg@4245: class TypeParameter; // a formal type parameter declared in generic signatures kamg@4245: class TypeArgument; // The "type value" passed to fill parameters in supertypes kamg@4245: class TypeVariable; // A usage of a type parameter as a value kamg@4245: /** kamg@4245: * Example: kamg@4245: * kamg@4245: * class Foo extends Bar { int m(V v) {} } kamg@4245: * ^^^^^^ ^^^^^^ ^^ kamg@4245: * type parameters type argument type variable kamg@4245: * kamg@4245: * Note that a type variable could be passed as an argument too: kamg@4245: * class Foo extends Bar { int m(V v) {} } kamg@4245: * ^^^ kamg@4245: * type argument's value is a type variable kamg@4245: */ kamg@4245: kamg@4245: kamg@4245: class Type; kamg@4245: class ClassType; kamg@4245: class ArrayType; kamg@4245: class PrimitiveType; kamg@4245: class Context; kamg@4245: class DescriptorCache; kamg@4245: kamg@4245: class DescriptorStream; kamg@4245: kamg@4245: class Identifier : public ResourceObj { kamg@4245: private: kamg@4245: Symbol* _sym; kamg@4245: int _begin; kamg@4245: int _end; kamg@4245: kamg@4245: public: kamg@4245: Identifier(Symbol* sym, int begin, int end) : kamg@4245: _sym(sym), _begin(begin), _end(end) {} kamg@4245: kamg@4245: bool equals(Identifier* other); kamg@4245: bool equals(Symbol* sym); kamg@4245: kamg@4245: #ifndef PRODUCT kamg@4245: void print_on(outputStream* str) const; kamg@4245: #endif // ndef PRODUCT kamg@4245: }; kamg@4245: kamg@4245: class Descriptor : public ResourceObj { kamg@4245: protected: kamg@4245: GrowableArray _type_parameters; kamg@4245: ClassDescriptor* _outer_class; kamg@4245: kamg@4245: Descriptor(GrowableArray& params, kamg@4245: ClassDescriptor* outer) kamg@4245: : _type_parameters(params), _outer_class(outer) {} kamg@4245: kamg@4245: public: kamg@4245: kamg@4245: ClassDescriptor* outer_class() { return _outer_class; } kamg@4245: void set_outer_class(ClassDescriptor* sig) { _outer_class = sig; } kamg@4245: kamg@4245: virtual ClassDescriptor* as_class_signature() { return NULL; } kamg@4245: virtual MethodDescriptor* as_method_signature() { return NULL; } kamg@4245: kamg@4245: bool is_class_signature() { return as_class_signature() != NULL; } kamg@4245: bool is_method_signature() { return as_method_signature() != NULL; } kamg@4245: kamg@4245: GrowableArray& type_parameters() { kamg@4245: return _type_parameters; kamg@4245: } kamg@4245: kamg@4245: TypeParameter* find_type_parameter(Identifier* id, int* param_depth); kamg@4245: kamg@4245: virtual void bind_variables_to_parameters() = 0; kamg@4245: kamg@4245: #ifndef PRODUCT kamg@4245: virtual void print_on(outputStream* str) const = 0; kamg@4245: #endif kamg@4245: }; kamg@4245: kamg@4245: class ClassDescriptor : public Descriptor { kamg@4245: private: kamg@4245: ClassType* _super; kamg@4245: GrowableArray _interfaces; kamg@4245: MethodDescriptor* _outer_method; kamg@4245: kamg@4245: ClassDescriptor(GrowableArray& ftp, ClassType* scs, kamg@4245: GrowableArray& sis, ClassDescriptor* outer_class = NULL, kamg@4245: MethodDescriptor* outer_method = NULL) kamg@4245: : Descriptor(ftp, outer_class), _super(scs), _interfaces(sis), kamg@4245: _outer_method(outer_method) {} kamg@4245: kamg@4245: static u2 get_outer_class_index(InstanceKlass* k, TRAPS); kamg@4245: static ClassDescriptor* parse_generic_signature(Klass* k, Symbol* original_name, TRAPS); kamg@4245: kamg@4245: public: kamg@4245: kamg@4245: virtual ClassDescriptor* as_class_signature() { return this; } kamg@4245: kamg@4245: MethodDescriptor* outer_method() { return _outer_method; } kamg@4245: void set_outer_method(MethodDescriptor* m) { _outer_method = m; } kamg@4245: kamg@4245: ClassType* super() { return _super; } kamg@4245: ClassType* interface_desc(Symbol* sym); kamg@4245: kamg@4245: static ClassDescriptor* parse_generic_signature(Klass* k, TRAPS); kamg@4245: static ClassDescriptor* parse_generic_signature(Symbol* sym); kamg@4245: kamg@4245: // For use in superclass chains in positions where this is no generic info kamg@4245: static ClassDescriptor* placeholder(InstanceKlass* klass); kamg@4245: kamg@4245: #ifndef PRODUCT kamg@4245: void print_on(outputStream* str) const; kamg@4245: #endif kamg@4245: kamg@4245: ClassDescriptor* canonicalize(Context* ctx); kamg@4245: kamg@4245: // Linking sets the position index in any contained TypeVariable type kamg@4245: // to correspond to the location of that identifier in the formal type kamg@4245: // parameters. kamg@4245: void bind_variables_to_parameters(); kamg@4245: }; kamg@4245: kamg@4245: class MethodDescriptor : public Descriptor { kamg@4245: private: kamg@4245: GrowableArray _parameters; kamg@4245: Type* _return_type; kamg@4245: GrowableArray _throws; kamg@4245: kamg@4245: MethodDescriptor(GrowableArray& ftp, ClassDescriptor* outer, kamg@4245: GrowableArray& sigs, Type* rt, GrowableArray& throws) kamg@4245: : Descriptor(ftp, outer), _parameters(sigs), _return_type(rt), kamg@4245: _throws(throws) {} kamg@4245: kamg@4245: public: kamg@4245: kamg@4245: static MethodDescriptor* parse_generic_signature(Method* m, ClassDescriptor* outer); kamg@4245: static MethodDescriptor* parse_generic_signature(Symbol* sym, ClassDescriptor* outer); kamg@4245: kamg@4245: MethodDescriptor* as_method_signature() { return this; } kamg@4245: kamg@4245: // Performs generic analysis on the method parameters to determine kamg@4245: // if both methods refer to the same argument types. kamg@4245: bool covariant_match(MethodDescriptor* other, Context* ctx); kamg@4245: kamg@4245: // Returns a new method descriptor with all generic variables kamg@4245: // removed and replaced with whatever is indicated using the Context. kamg@4245: MethodDescriptor* canonicalize(Context* ctx); kamg@4245: kamg@4245: void bind_variables_to_parameters(); kamg@4245: kamg@4245: #ifndef PRODUCT kamg@4245: TempNewSymbol reify_signature(Context* ctx, TRAPS); kamg@4245: void print_on(outputStream* str) const; kamg@4245: #endif kamg@4245: }; kamg@4245: kamg@4245: class TypeParameter : public ResourceObj { kamg@4245: private: kamg@4245: Identifier* _identifier; kamg@4245: ClassType* _class_bound; kamg@4245: GrowableArray _interface_bounds; kamg@4245: kamg@4245: // The position is the ordinal location of the parameter within the kamg@4245: // formal parameter list (excluding outer classes). It is only set for kamg@4245: // formal type parameters that are associated with a class -- method kamg@4245: // type parameters are left as -1. When resolving a generic variable to kamg@4245: // find the actual type, this index is used to access the generic type kamg@4245: // argument in the provided context object. kamg@4245: int _position; // Assigned during variable linking kamg@4245: kamg@4245: TypeParameter(Identifier* id, ClassType* class_bound, kamg@4245: GrowableArray& interface_bounds) : kamg@4245: _identifier(id), _class_bound(class_bound), kamg@4245: _interface_bounds(interface_bounds), _position(-1) {} kamg@4245: kamg@4245: public: kamg@4245: static TypeParameter* parse_generic_signature(DescriptorStream* str); kamg@4245: kamg@4245: ClassType* bound(); kamg@4245: int position() { return _position; } kamg@4245: kamg@4245: void bind_variables_to_parameters(Descriptor* sig, int position); kamg@4245: Identifier* identifier() { return _identifier; } kamg@4245: kamg@4245: Type* resolve(Context* ctx, int inner_depth, int ctx_depth); kamg@4245: TypeParameter* canonicalize(Context* ctx, int ctx_depth); kamg@4245: kamg@4245: #ifndef PRODUCT kamg@4245: void print_on(outputStream* str) const; kamg@4245: #endif kamg@4245: }; kamg@4245: kamg@4245: class Type : public ResourceObj { kamg@4245: public: kamg@4245: static Type* parse_generic_signature(DescriptorStream* str); kamg@4245: kamg@4245: virtual ClassType* as_class() { return NULL; } kamg@4245: virtual TypeVariable* as_variable() { return NULL; } kamg@4245: virtual ArrayType* as_array() { return NULL; } kamg@4245: virtual PrimitiveType* as_primitive() { return NULL; } kamg@4245: kamg@4245: virtual bool covariant_match(Type* gt, Context* ctx) = 0; kamg@4245: virtual Type* canonicalize(Context* ctx, int ctx_depth) = 0; kamg@4245: kamg@4245: virtual void bind_variables_to_parameters(Descriptor* sig) = 0; kamg@4245: kamg@4245: #ifndef PRODUCT kamg@4245: virtual void reify_signature(stringStream* ss, Context* ctx) = 0; kamg@4245: virtual void print_on(outputStream* str) const = 0; kamg@4245: #endif kamg@4245: }; kamg@4245: kamg@4245: class ClassType : public Type { kamg@4245: friend class ClassDescriptor; kamg@4245: protected: kamg@4245: Identifier* _identifier; kamg@4245: GrowableArray _type_arguments; kamg@4245: ClassType* _outer_class; kamg@4245: kamg@4245: ClassType(Identifier* identifier, kamg@4245: GrowableArray& args, kamg@4245: ClassType* outer) kamg@4245: : _identifier(identifier), _type_arguments(args), _outer_class(outer) {} kamg@4245: kamg@4245: // Returns true if there are inner classes to read kamg@4245: static Identifier* parse_generic_signature_simple( kamg@4245: GrowableArray* args, kamg@4245: bool* has_inner, DescriptorStream* str); kamg@4245: kamg@4245: static ClassType* parse_generic_signature(ClassType* outer, kamg@4245: DescriptorStream* str); kamg@4245: static ClassType* from_symbol(Symbol* sym); kamg@4245: kamg@4245: public: kamg@4245: ClassType* as_class() { return this; } kamg@4245: kamg@4245: static ClassType* parse_generic_signature(DescriptorStream* str); kamg@4245: static ClassType* java_lang_Object(); kamg@4245: kamg@4245: Identifier* identifier() { return _identifier; } kamg@4245: int type_arguments_length() { return _type_arguments.length(); } kamg@4245: TypeArgument* type_argument_at(int i); kamg@4245: kamg@4245: virtual ClassType* outer_class() { return _outer_class; } kamg@4245: kamg@4245: bool covariant_match(Type* gt, Context* ctx); kamg@4245: ClassType* canonicalize(Context* ctx, int context_depth); kamg@4245: kamg@4245: void bind_variables_to_parameters(Descriptor* sig); kamg@4245: kamg@4245: #ifndef PRODUCT kamg@4245: void reify_signature(stringStream* ss, Context* ctx); kamg@4245: void print_on(outputStream* str) const; kamg@4245: #endif kamg@4245: }; kamg@4245: kamg@4245: class TypeVariable : public Type { kamg@4245: private: kamg@4245: Identifier* _id; kamg@4245: TypeParameter* _parameter; // assigned during linking kamg@4245: kamg@4245: // how many steps "out" from inner classes, -1 if method kamg@4245: int _inner_depth; kamg@4245: kamg@4245: TypeVariable(Identifier* id) kamg@4245: : _id(id), _parameter(NULL), _inner_depth(0) {} kamg@4245: kamg@4245: public: kamg@4245: TypeVariable* as_variable() { return this; } kamg@4245: kamg@4245: static TypeVariable* parse_generic_signature(DescriptorStream* str); kamg@4245: kamg@4245: Identifier* identifier() { return _id; } kamg@4245: TypeParameter* parameter() { return _parameter; } kamg@4245: int inner_depth() { return _inner_depth; } kamg@4245: kamg@4245: void bind_variables_to_parameters(Descriptor* sig); kamg@4245: kamg@4245: Type* resolve(Context* ctx, int ctx_depth); kamg@4245: bool covariant_match(Type* gt, Context* ctx); kamg@4245: Type* canonicalize(Context* ctx, int ctx_depth); kamg@4245: kamg@4245: #ifndef PRODUCT kamg@4245: void reify_signature(stringStream* ss, Context* ctx); kamg@4245: void print_on(outputStream* str) const; kamg@4245: #endif kamg@4245: }; kamg@4245: kamg@4245: class ArrayType : public Type { kamg@4245: private: kamg@4245: Type* _base; kamg@4245: kamg@4245: ArrayType(Type* base) : _base(base) {} kamg@4245: kamg@4245: public: kamg@4245: ArrayType* as_array() { return this; } kamg@4245: kamg@4245: static ArrayType* parse_generic_signature(DescriptorStream* str); kamg@4245: kamg@4245: bool covariant_match(Type* gt, Context* ctx); kamg@4245: ArrayType* canonicalize(Context* ctx, int ctx_depth); kamg@4245: kamg@4245: void bind_variables_to_parameters(Descriptor* sig); kamg@4245: kamg@4245: #ifndef PRODUCT kamg@4245: void reify_signature(stringStream* ss, Context* ctx); kamg@4245: void print_on(outputStream* str) const; kamg@4245: #endif kamg@4245: }; kamg@4245: kamg@4245: class PrimitiveType : public Type { kamg@4245: friend class Type; kamg@4245: private: kamg@4245: char _type; // includes V for void kamg@4245: kamg@4245: PrimitiveType(char& type) : _type(type) {} kamg@4245: kamg@4245: public: kamg@4245: PrimitiveType* as_primitive() { return this; } kamg@4245: kamg@4245: bool covariant_match(Type* gt, Context* ctx); kamg@4245: PrimitiveType* canonicalize(Context* ctx, int ctx_depth); kamg@4245: kamg@4245: void bind_variables_to_parameters(Descriptor* sig); kamg@4245: kamg@4245: #ifndef PRODUCT kamg@4245: void reify_signature(stringStream* ss, Context* ctx); kamg@4245: void print_on(outputStream* str) const; kamg@4245: #endif kamg@4245: }; kamg@4245: kamg@4245: class TypeArgument : public ResourceObj { kamg@4245: private: kamg@4245: Type* _lower_bound; kamg@4245: Type* _upper_bound; // may be null or == _lower_bound kamg@4245: kamg@4245: TypeArgument(Type* lower_bound, Type* upper_bound) kamg@4245: : _lower_bound(lower_bound), _upper_bound(upper_bound) {} kamg@4245: kamg@4245: public: kamg@4245: kamg@4245: static TypeArgument* parse_generic_signature(DescriptorStream* str); kamg@4245: kamg@4245: Type* lower_bound() { return _lower_bound; } kamg@4245: Type* upper_bound() { return _upper_bound; } kamg@4245: kamg@4245: void bind_variables_to_parameters(Descriptor* sig); kamg@4245: TypeArgument* canonicalize(Context* ctx, int ctx_depth); kamg@4245: kamg@4245: bool covariant_match(TypeArgument* a, Context* ctx); kamg@4245: kamg@4245: #ifndef PRODUCT kamg@4245: void print_on(outputStream* str) const; kamg@4245: #endif kamg@4245: }; kamg@4245: kamg@4245: kamg@4245: class Context : public ResourceObj { kamg@4245: private: kamg@4245: DescriptorCache* _cache; kamg@4245: GrowableArray _type_arguments; kamg@4245: kamg@4245: void reset_to_mark(int size); kamg@4245: kamg@4245: public: kamg@4245: // When this object goes out of scope or 'destroy' is kamg@4245: // called, then the application of the type to the kamg@4245: // context is wound-back (unless it's been deactivated). kamg@4245: class Mark : public StackObj { kamg@4245: private: kamg@4245: mutable Context* _context; kamg@4245: int _marked_size; kamg@4245: kamg@4245: bool is_active() const { return _context != NULL; } kamg@4245: void deactivate() const { _context = NULL; } kamg@4245: kamg@4245: public: kamg@4245: Mark() : _context(NULL), _marked_size(0) {} kamg@4245: Mark(Context* ctx, int sz) : _context(ctx), _marked_size(sz) {} kamg@4245: Mark(const Mark& m) : _context(m._context), _marked_size(m._marked_size) { kamg@4245: m.deactivate(); // Ownership is transferred kamg@4245: } kamg@4245: kamg@4245: Mark& operator=(const Mark& cm) { kamg@4245: destroy(); kamg@4245: _context = cm._context; kamg@4245: _marked_size = cm._marked_size; kamg@4245: cm.deactivate(); kamg@4245: return *this; kamg@4245: } kamg@4245: kamg@4245: void destroy(); kamg@4245: ~Mark() { destroy(); } kamg@4245: }; kamg@4245: kamg@4245: Context(DescriptorCache* cache) : _cache(cache) {} kamg@4245: kamg@4245: Mark mark() { return Mark(this, _type_arguments.length()); } kamg@4245: void apply_type_arguments(InstanceKlass* current, InstanceKlass* super,TRAPS); kamg@4245: kamg@4245: ClassType* at_depth(int i) const; kamg@4245: kamg@4245: #ifndef PRODUCT kamg@4245: void print_on(outputStream* str) const; kamg@4245: #endif kamg@4245: }; kamg@4245: kamg@4245: /** kamg@4245: * Contains a cache of descriptors for classes and methods so they can be kamg@4245: * looked-up instead of reparsing each time they are needed. kamg@4245: */ kamg@4245: class DescriptorCache : public ResourceObj { kamg@4245: private: kamg@4245: ResourceHashtable _class_descriptors; kamg@4245: ResourceHashtable _method_descriptors; kamg@4245: kamg@4245: public: kamg@4245: ClassDescriptor* descriptor_for(InstanceKlass* ikh, TRAPS); kamg@4245: kamg@4245: MethodDescriptor* descriptor_for(Method* mh, ClassDescriptor* cd, TRAPS); kamg@4245: // Class descriptor derived from method holder kamg@4245: MethodDescriptor* descriptor_for(Method* mh, TRAPS); kamg@4245: }; kamg@4245: kamg@4245: } // namespace generic kamg@4245: kamg@4245: #endif // SHARE_VM_CLASSFILE_GENERICSIGNATURES_HPP kamg@4245: