< prev index next >
src/hotspot/share/runtime/signature.hpp
Print this page
*** 23,272 ****
*/
#ifndef SHARE_RUNTIME_SIGNATURE_HPP
#define SHARE_RUNTIME_SIGNATURE_HPP
#include "memory/allocation.hpp"
#include "oops/method.hpp"
! // SignatureIterators iterate over a Java signature (or parts of it).
! // (Syntax according to: "The Java Virtual Machine Specification" by
! // Tim Lindholm & Frank Yellin; section 4.3 Descriptors; p. 89ff.)
//
! // Example: Iterating over ([Lfoo;D)I using
! // 0123456789
//
! // iterate_parameters() calls: do_array(2, 7); do_double();
! // iterate_returntype() calls: do_int();
! // iterate() calls: do_array(2, 7); do_double(); do_int();
//
! // is_return_type() is: false ; false ; true
//
! // NOTE: The new optimizer has an alternate, for-loop based signature
! // iterator implemented in opto/type.cpp, TypeTuple::make().
class SignatureIterator: public ResourceObj {
protected:
Symbol* _signature; // the signature to iterate over
- int _index; // the current character index (only valid during iteration)
- int _parameter_index; // the current parameter index (0 outside iteration phase)
BasicType _return_type;
!
! void expect(char c);
! int parse_type(); // returns the parameter size in words (0 for void)
! void check_signature_end();
public:
// Definitions used in generating and iterating the
// bit field form of the signature generated by the
// Fingerprinter.
enum {
! static_feature_size = 1,
! is_static_bit = 1,
! result_feature_size = 4,
! result_feature_mask = 0xF,
! parameter_feature_size = 4,
! parameter_feature_mask = 0xF,
!
! bool_parm = 1,
! byte_parm = 2,
! char_parm = 3,
! short_parm = 4,
! int_parm = 5,
! long_parm = 6,
! float_parm = 7,
! double_parm = 8,
! obj_parm = 9,
! done_parm = 10, // marker for end of parameters
!
! // max parameters is wordsize minus
! // The sign bit, termination field, the result and static bit fields
! max_size_of_parameters = (BitsPerLong-1 -
! result_feature_size - parameter_feature_size -
! static_feature_size) / parameter_feature_size
};
// Constructors
! SignatureIterator(Symbol* signature);
// Iteration
! void iterate_parameters(); // iterates over parameters only
! void iterate_parameters( uint64_t fingerprint );
! void iterate_returntype(); // iterates over returntype only
! void iterate(); // iterates over whole signature
! // Returns the word index of the current parameter;
! int parameter_index() const { return _parameter_index; }
! bool is_return_type() const { return parameter_index() < 0; }
! BasicType get_ret_type() const { return _return_type; }
!
! // Basic types
! virtual void do_bool () = 0;
! virtual void do_char () = 0;
! virtual void do_float () = 0;
! virtual void do_double() = 0;
! virtual void do_byte () = 0;
! virtual void do_short () = 0;
! virtual void do_int () = 0;
! virtual void do_long () = 0;
! virtual void do_void () = 0;
!
! // Object types (begin indexes the first character of the entry, end indexes the first character after the entry)
! virtual void do_object(int begin, int end) = 0;
! virtual void do_array (int begin, int end) = 0;
!
! static bool is_static(uint64_t fingerprint) {
! assert(fingerprint != (uint64_t)CONST64(-1), "invalid fingerprint");
! return fingerprint & is_static_bit;
! }
! static BasicType return_type(uint64_t fingerprint) {
! assert(fingerprint != (uint64_t)CONST64(-1), "invalid fingerprint");
! return (BasicType) ((fingerprint >> static_feature_size) & result_feature_mask);
}
};
// Specialized SignatureIterators: Used to compute signature specific values.
class SignatureTypeNames : public SignatureIterator {
protected:
virtual void type_name(const char* name) = 0;
! void do_bool() { type_name("jboolean"); }
! void do_char() { type_name("jchar" ); }
! void do_float() { type_name("jfloat" ); }
! void do_double() { type_name("jdouble" ); }
! void do_byte() { type_name("jbyte" ); }
! void do_short() { type_name("jshort" ); }
! void do_int() { type_name("jint" ); }
! void do_long() { type_name("jlong" ); }
! void do_void() { type_name("void" ); }
! void do_object(int begin, int end) { type_name("jobject" ); }
! void do_array (int begin, int end) { type_name("jobject" ); }
public:
SignatureTypeNames(Symbol* signature) : SignatureIterator(signature) {}
};
! class SignatureInfo: public SignatureIterator {
! protected:
! bool _has_iterated; // need this because iterate cannot be called in constructor (set is virtual!)
! bool _has_iterated_return;
! int _size;
!
! void lazy_iterate_parameters() { if (!_has_iterated) { iterate_parameters(); _has_iterated = true; } }
! void lazy_iterate_return() { if (!_has_iterated_return) { iterate_returntype(); _has_iterated_return = true; } }
!
! virtual void set(int size, BasicType type) = 0;
!
! void do_bool () { set(T_BOOLEAN_size, T_BOOLEAN); }
! void do_char () { set(T_CHAR_size , T_CHAR ); }
! void do_float () { set(T_FLOAT_size , T_FLOAT ); }
! void do_double() { set(T_DOUBLE_size , T_DOUBLE ); }
! void do_byte () { set(T_BYTE_size , T_BYTE ); }
! void do_short () { set(T_SHORT_size , T_SHORT ); }
! void do_int () { set(T_INT_size , T_INT ); }
! void do_long () { set(T_LONG_size , T_LONG ); }
! void do_void () { set(T_VOID_size , T_VOID ); }
! void do_object(int begin, int end) { set(T_OBJECT_size , T_OBJECT ); }
! void do_array (int begin, int end) { set(T_ARRAY_size , T_ARRAY ); }
!
! public:
! SignatureInfo(Symbol* signature) : SignatureIterator(signature) {
! _has_iterated = _has_iterated_return = false;
! _size = 0;
! _return_type = T_ILLEGAL;
! }
};
! // Specialized SignatureIterator: Used to compute the argument size.
!
! class ArgumentSizeComputer: public SignatureInfo {
private:
! void set(int size, BasicType type) { _size += size; }
public:
! ArgumentSizeComputer(Symbol* signature) : SignatureInfo(signature) {}
!
! int size() { lazy_iterate_parameters(); return _size; }
};
! class ArgumentCount: public SignatureInfo {
private:
! void set(int size, BasicType type) { _size ++; }
public:
! ArgumentCount(Symbol* signature) : SignatureInfo(signature) {}
!
! int size() { lazy_iterate_parameters(); return _size; }
};
// Specialized SignatureIterator: Used to compute the result type.
! class ResultTypeFinder: public SignatureInfo {
! private:
! void set(int size, BasicType type) { _return_type = type; }
public:
! BasicType type() { lazy_iterate_return(); return _return_type; }
!
! ResultTypeFinder(Symbol* signature) : SignatureInfo(signature) {}
};
// Fingerprinter computes a unique ID for a given method. The ID
// is a bitvector characterizing the methods signature (incl. the receiver).
class Fingerprinter: public SignatureIterator {
private:
! uint64_t _fingerprint;
int _shift_count;
! methodHandle mh;
!
! public:
!
! void do_bool() { _fingerprint |= (((uint64_t)bool_parm) << _shift_count); _shift_count += parameter_feature_size; }
! void do_char() { _fingerprint |= (((uint64_t)char_parm) << _shift_count); _shift_count += parameter_feature_size; }
! void do_byte() { _fingerprint |= (((uint64_t)byte_parm) << _shift_count); _shift_count += parameter_feature_size; }
! void do_short() { _fingerprint |= (((uint64_t)short_parm) << _shift_count); _shift_count += parameter_feature_size; }
! void do_int() { _fingerprint |= (((uint64_t)int_parm) << _shift_count); _shift_count += parameter_feature_size; }
! void do_long() { _fingerprint |= (((uint64_t)long_parm) << _shift_count); _shift_count += parameter_feature_size; }
! void do_float() { _fingerprint |= (((uint64_t)float_parm) << _shift_count); _shift_count += parameter_feature_size; }
! void do_double() { _fingerprint |= (((uint64_t)double_parm) << _shift_count); _shift_count += parameter_feature_size; }
!
! void do_object(int begin, int end) { _fingerprint |= (((uint64_t)obj_parm) << _shift_count); _shift_count += parameter_feature_size; }
! void do_array (int begin, int end) { _fingerprint |= (((uint64_t)obj_parm) << _shift_count); _shift_count += parameter_feature_size; }
!
! void do_void() { ShouldNotReachHere(); }
! Fingerprinter(const methodHandle& method) : SignatureIterator(method->signature()) {
! mh = method;
! _fingerprint = 0;
}
! uint64_t fingerprint() {
! // See if we fingerprinted this method already
! if (mh->constMethod()->fingerprint() != CONST64(0)) {
! return mh->constMethod()->fingerprint();
! }
!
! if (mh->size_of_parameters() > max_size_of_parameters ) {
! _fingerprint = (uint64_t)CONST64(-1);
! mh->constMethod()->set_fingerprint(_fingerprint);
! return _fingerprint;
! }
! assert( (int)mh->result_type() <= (int)result_feature_mask, "bad result type");
! _fingerprint = mh->result_type();
! _fingerprint <<= static_feature_size;
! if (mh->is_static()) _fingerprint |= 1;
! _shift_count = result_feature_size + static_feature_size;
! iterate_parameters();
! _fingerprint |= ((uint64_t)done_parm) << _shift_count;// mark end of sig
! mh->constMethod()->set_fingerprint(_fingerprint);
! return _fingerprint;
}
};
// Specialized SignatureIterator: Used for native call purposes
--- 23,374 ----
*/
#ifndef SHARE_RUNTIME_SIGNATURE_HPP
#define SHARE_RUNTIME_SIGNATURE_HPP
+ #include "classfile/symbolTable.hpp"
#include "memory/allocation.hpp"
#include "oops/method.hpp"
!
! // Static routines and parsing loops for processing field and method
! // descriptors. In the HotSpot sources we call them "signatures".
! //
! // A SignatureStream iterates over a Java descriptor (or parts of it).
! // The syntax is documented in the Java Virtual Machine Specification,
! // section 4.3.
! //
! // The syntax may be summarized as follows:
! //
! // MethodType: '(' {FieldType}* ')' (FieldType | 'V')
! // FieldType: PrimitiveType | ObjectType | ArrayType
! // PrimitiveType: 'B' | 'C' | 'D' | 'F' | 'I' | 'J' | 'S' | 'Z'
! // ObjectType: ('L' | 'Q') ClassName ';' | ArrayType
! // ArrayType: '[' FieldType
! // ClassName: {UnqualifiedName '/'}* UnqualifiedName
! // UnqualifiedName: NameChar {NameChar}*
! // NameChar: ANY_CHAR_EXCEPT('/' | '.' | ';' | '[')
! //
! // All of the concrete characters in the above grammar are given
! // standard manifest constant names of the form JVM_SIGNATURE_x.
! // Executable code uses these constant names in preference to raw
! // character constants. Comments and assertion code sometimes use
! // the raw character constants for brevity.
//
! // The primitive field types (like 'I') correspond 1-1 with type codes
! // (like T_INT) which part of the specfication of the 'newarray'
! // instruction (JVMS 6.5, section on newarray). These type codes are
! // widely used in the HotSpot code. They are joined by ad hoc codes
! // like T_OBJECT and T_ARRAY (defined in HotSpot but not in the JVMS)
! // so that each "basic type" of field descriptor (or void return type)
! // has a corresponding T_x code. Thus, while T_x codes play a very
! // minor role in the JVMS, they play a major role in the HotSpot
! // sources. There are fewer than 16 such "basic types", so they fit
! // nicely into bitfields.
//
! // The syntax of ClassName overlaps slightly with the descriptor
! // syntaxes. The strings "I" and "(I)V" are both class names
! // *and* descriptors. If a class name contains any character other
! // than "BCDFIJSZ()V" it cannot be confused with a descriptor.
! // Class names inside of descriptors are always contained in an
! // "envelope" syntax which starts with 'L' (or 'Q') and ends with ';'.
//
! // As a confounding factor, array types report their type name strings
! // in descriptor format. These name strings are easy to recognize,
! // since they begin with '['. For this reason some API points on
! // HotSpot look for array descriptors as well as proper class names.
//
! // For historical reasons some API points that accept class names and
! // array names also look for class names wrapped inside an envelope
! // (like "LFoo;") and unwrap them on the fly (to a name like "Foo").
!
! class Signature : AllStatic {
! private:
! static bool is_valid_array_signature(const Symbol* sig);
!
! public:
!
! // Returns the basic type of a field signature (or T_VOID for "V").
! // Assumes the signature is a valid field descriptor.
! // Do not apply this function to class names or method signatures.
! static BasicType basic_type(const Symbol* signature) {
! return basic_type(signature->char_at(0));
! }
!
! // Returns T_ILLEGAL for an illegal signature char.
! static BasicType basic_type(int ch);
!
! // Assuming it is either a class name or signature,
! // determine if it (in fact) cannot be a class name.
! // This means it either starts with '[' or ends with ';'
! static bool not_class_name(const Symbol* signature) {
! return (signature->starts_with(JVM_SIGNATURE_ARRAY) ||
! signature->ends_with(JVM_SIGNATURE_ENDCLASS));
! }
!
! // Assuming it is either a class name or signature,
! // determine if it (in fact) is an array descriptor.
! static bool is_array(const Symbol* signature) {
! return (signature->utf8_length() > 1 &&
! signature->char_at(0) == JVM_SIGNATURE_ARRAY &&
! is_valid_array_signature(signature));
! }
!
! // Assuming it is either a class name or signature,
! // determine if it contains a class name plus ';'.
! static bool has_envelope(const Symbol* signature) {
! return ((signature->utf8_length() > 0) &&
! signature->ends_with(JVM_SIGNATURE_ENDCLASS) &&
! has_envelope(signature->char_at(0)));
! }
!
! // Determine if this signature char introduces an
! // envelope, which is a class name plus ';'.
! static bool has_envelope(char signature_char) {
! return (signature_char == JVM_SIGNATURE_CLASS);
! }
!
! // Assuming has_envelope is true, return the symbol
! // inside the envelope, by stripping 'L' and ';'.
! // Caller is responsible for decrementing the newly created
! // Symbol's refcount, use TempNewSymbol.
! static Symbol* strip_envelope(const Symbol* signature) {
! assert(has_envelope(signature), "precondition");
! return SymbolTable::new_symbol((char*) signature->bytes() + 1,
! signature->utf8_length() - 2);
! }
!
! // Assuming it's either a field or method descriptor, determine
! // whether it is in fact a method descriptor:
! static bool is_method(const Symbol* signature) {
! return signature->starts_with(JVM_SIGNATURE_FUNC);
! }
!
! // Assuming it's a method signature, determine if it must
! // return void.
! static bool is_void_method(const Symbol* signature) {
! assert(is_method(signature), "signature is not for a method");
! return signature->ends_with(JVM_SIGNATURE_VOID);
! }
! };
!
! // A SignatureIterator uses a SignatureStream to produces BasicType
! // results, discarding class names. This means it can be accelerated
! // using a fingerprint mechanism, in many cases, without loss of type
! // information. The FingerPrinter class computes and caches this
! // reduced information for faster iteration.
class SignatureIterator: public ResourceObj {
+ public:
+ typedef uint64_t fingerprint_t;
+
protected:
Symbol* _signature; // the signature to iterate over
BasicType _return_type;
! fingerprint_t _fingerprint;
public:
// Definitions used in generating and iterating the
// bit field form of the signature generated by the
// Fingerprinter.
enum {
! fp_static_feature_size = 1,
! fp_is_static_bit = 1,
! fp_result_feature_size = 4,
! fp_result_feature_mask = right_n_bits(fp_result_feature_size),
! fp_parameter_feature_size = 4,
! fp_parameter_feature_mask = right_n_bits(fp_parameter_feature_size),
!
! fp_parameters_done = 0, // marker for end of parameters (must be zero)
!
! // Parameters take up full wordsize, minus the result and static bit fields.
! // Since fp_parameters_done is zero, termination field arises from shifting
! // in zero bits, and therefore occupies no extra space.
! // The sentinel value is all-zero-bits, which is impossible for a true
! // fingerprint, since at least the result field will be non-zero.
! fp_max_size_of_parameters = ((BitsPerLong
! - (fp_result_feature_size + fp_static_feature_size))
! / fp_parameter_feature_size)
};
+ static bool fp_is_valid_type(BasicType type, bool for_return_type = false);
+
+ // Sentinel values are zero and not-zero (-1).
+ // No need to protect the sign bit, since every valid return type is non-zero
+ // (even T_VOID), and there are no valid parameter fields which are 0xF (T_VOID).
+ static fingerprint_t zero_fingerprint() { return (fingerprint_t)0; }
+ static fingerprint_t overflow_fingerprint() { return ~(fingerprint_t)0; }
+ static bool fp_is_valid(fingerprint_t fingerprint) {
+ return (fingerprint != zero_fingerprint()) && (fingerprint != overflow_fingerprint());
+ }
+
// Constructors
! SignatureIterator(Symbol* signature, fingerprint_t fingerprint = zero_fingerprint()) {
! _signature = signature;
! _return_type = T_ILLEGAL; // sentinel value for uninitialized
! _fingerprint = zero_fingerprint();
! if (fingerprint != _fingerprint) {
! set_fingerprint(fingerprint);
! }
! }
!
! // If the fingerprint is present, we can use an accelerated loop.
! void set_fingerprint(fingerprint_t fingerprint);
!
! // Returns the set fingerprint, or zero_fingerprint()
! // if none has been set already.
! fingerprint_t fingerprint() const { return _fingerprint; }
// Iteration
! // Hey look: There are no virtual methods in this class.
! // So how is it customized? By calling do_parameters_on
! // an object which answers to "do_type(BasicType)".
! // By convention, this object is in the subclass
! // itself, so the call is "do_parameters_on(this)".
! // The effect of this is to inline the parsing loop
! // everywhere "do_parameters_on" is called.
! // If there is a valid fingerprint in the object,
! // an improved loop is called which just unpacks the
! // bitfields from the fingerprint. Otherwise, the
! // symbol is parsed.
! template<typename T> inline void do_parameters_on(T* callback); // iterates over parameters only
! void skip_parameters(); // skips over parameters to find return type
! BasicType return_type(); // computes the value on the fly if necessary
!
! static bool fp_is_static(fingerprint_t fingerprint) {
! assert(fp_is_valid(fingerprint), "invalid fingerprint");
! return fingerprint & fp_is_static_bit;
! }
! static BasicType fp_return_type(fingerprint_t fingerprint) {
! assert(fp_is_valid(fingerprint), "invalid fingerprint");
! return (BasicType) ((fingerprint >> fp_static_feature_size) & fp_result_feature_mask);
! }
! static fingerprint_t fp_start_parameters(fingerprint_t fingerprint) {
! assert(fp_is_valid(fingerprint), "invalid fingerprint");
! return fingerprint >> (fp_static_feature_size + fp_result_feature_size);
! }
! static BasicType fp_next_parameter(fingerprint_t& mask) {
! int result = (mask & fp_parameter_feature_mask);
! mask >>= fp_parameter_feature_size;
! return (BasicType) result;
}
};
// Specialized SignatureIterators: Used to compute signature specific values.
class SignatureTypeNames : public SignatureIterator {
protected:
virtual void type_name(const char* name) = 0;
! friend class SignatureIterator; // so do_parameters_on can call do_type
! void do_type(BasicType type) {
! switch (type) {
! case T_BOOLEAN: type_name("jboolean"); break;
! case T_CHAR: type_name("jchar" ); break;
! case T_FLOAT: type_name("jfloat" ); break;
! case T_DOUBLE: type_name("jdouble" ); break;
! case T_BYTE: type_name("jbyte" ); break;
! case T_SHORT: type_name("jshort" ); break;
! case T_INT: type_name("jint" ); break;
! case T_LONG: type_name("jlong" ); break;
! case T_VOID: type_name("void" ); break;
! case T_ARRAY:
! case T_OBJECT: type_name("jobject" ); break;
! default: ShouldNotReachHere();
! }
! }
public:
SignatureTypeNames(Symbol* signature) : SignatureIterator(signature) {}
};
! // Specialized SignatureIterator: Used to compute the argument size.
+ class ArgumentSizeComputer: public SignatureIterator {
+ private:
+ int _size;
+ friend class SignatureIterator; // so do_parameters_on can call do_type
+ void do_type(BasicType type) { _size += parameter_type_word_count(type); }
+ public:
+ ArgumentSizeComputer(Symbol* signature);
+ int size() { return _size; }
};
! class ArgumentCount: public SignatureIterator {
private:
! int _size;
! friend class SignatureIterator; // so do_parameters_on can call do_type
! void do_type(BasicType type) { _size++; }
public:
! ArgumentCount(Symbol* signature);
! int size() { return _size; }
};
! class ReferenceArgumentCount: public SignatureIterator {
private:
! int _refs;
! friend class SignatureIterator; // so do_parameters_on can call do_type
! void do_type(BasicType type) { if (is_reference_type(type)) _refs++; }
public:
! ReferenceArgumentCount(Symbol* signature);
! int count() { return _refs; }
};
// Specialized SignatureIterator: Used to compute the result type.
! class ResultTypeFinder: public SignatureIterator {
public:
! BasicType type() { return return_type(); }
! ResultTypeFinder(Symbol* signature) : SignatureIterator(signature) { }
};
// Fingerprinter computes a unique ID for a given method. The ID
// is a bitvector characterizing the methods signature (incl. the receiver).
class Fingerprinter: public SignatureIterator {
private:
! fingerprint_t _accumulator;
! int _param_size;
int _shift_count;
! const Method* _method;
! void initialize_accumulator() {
! _accumulator = 0;
! _shift_count = fp_result_feature_size + fp_static_feature_size;
! _param_size = 0;
! }
!
! // Out-of-line method does it all in constructor:
! void compute_fingerprint_and_return_type(bool static_flag = false);
!
! friend class SignatureIterator; // so do_parameters_on can call do_type
! void do_type(BasicType type) {
! assert(fp_is_valid_type(type), "bad parameter type");
! _accumulator |= ((fingerprint_t)type << _shift_count);
! _shift_count += fp_parameter_feature_size;
! _param_size += (is_double_word_type(type) ? 2 : 1);
}
! public:
! int size_of_parameters() const { return _param_size; }
! // fingerprint() and return_type() are in super class
! Fingerprinter(const methodHandle& method)
! : SignatureIterator(method->signature()),
! _method(method()) {
! compute_fingerprint_and_return_type();
! }
! Fingerprinter(Symbol* signature, bool is_static)
! : SignatureIterator(signature),
! _method(NULL) {
! compute_fingerprint_and_return_type(is_static);
}
};
// Specialized SignatureIterator: Used for native call purposes
*** 279,317 ****
// For example a long takes up 1 "C" stack entry but 2 Java stack entries.
int _offset; // The java stack offset
int _prepended; // number of prepended JNI parameters (1 JNIEnv, plus 1 mirror if static)
int _jni_offset; // the current parameter offset, starting with 0
! void do_bool () { pass_int(); _jni_offset++; _offset++; }
! void do_char () { pass_int(); _jni_offset++; _offset++; }
! void do_float () { pass_float(); _jni_offset++; _offset++; }
#ifdef _LP64
! void do_double() { pass_double(); _jni_offset++; _offset += 2; }
#else
! void do_double() { pass_double(); _jni_offset += 2; _offset += 2; }
#endif
! void do_byte () { pass_int(); _jni_offset++; _offset++; }
! void do_short () { pass_int(); _jni_offset++; _offset++; }
! void do_int () { pass_int(); _jni_offset++; _offset++; }
#ifdef _LP64
! void do_long () { pass_long(); _jni_offset++; _offset += 2; }
#else
! void do_long () { pass_long(); _jni_offset += 2; _offset += 2; }
#endif
! void do_void () { ShouldNotReachHere(); }
! void do_object(int begin, int end) { pass_object(); _jni_offset++; _offset++; }
! void do_array (int begin, int end) { pass_object(); _jni_offset++; _offset++; }
public:
methodHandle method() const { return _method; }
int offset() const { return _offset; }
int jni_offset() const { return _jni_offset + _prepended; }
- // int java_offset() const { return method()->size_of_parameters() - _offset - 1; }
bool is_static() const { return method()->is_static(); }
virtual void pass_int() = 0;
virtual void pass_long() = 0;
! virtual void pass_object() = 0;
virtual void pass_float() = 0;
#ifdef _LP64
virtual void pass_double() = 0;
#else
virtual void pass_double() { pass_long(); } // may be same as long
--- 381,431 ----
// For example a long takes up 1 "C" stack entry but 2 Java stack entries.
int _offset; // The java stack offset
int _prepended; // number of prepended JNI parameters (1 JNIEnv, plus 1 mirror if static)
int _jni_offset; // the current parameter offset, starting with 0
! friend class SignatureIterator; // so do_parameters_on can call do_type
! void do_type(BasicType type) {
! switch (type) {
! case T_BYTE: case T_SHORT: case T_INT:
! case T_BOOLEAN: case T_CHAR:
! pass_int(); _jni_offset++; _offset++;
! break;
! case T_FLOAT:
! pass_float(); _jni_offset++; _offset++;
! break;
! case T_DOUBLE:
#ifdef _LP64
! pass_double(); _jni_offset++; _offset += 2;
#else
! pass_double(); _jni_offset += 2; _offset += 2;
#endif
! break;
! case T_LONG:
#ifdef _LP64
! pass_long(); _jni_offset++; _offset += 2;
#else
! pass_long(); _jni_offset += 2; _offset += 2;
#endif
! break;
! case T_ARRAY:
! case T_OBJECT:
! pass_object(); _jni_offset++; _offset++;
! break;
! default:
! ShouldNotReachHere();
! }
! }
public:
methodHandle method() const { return _method; }
int offset() const { return _offset; }
int jni_offset() const { return _jni_offset + _prepended; }
bool is_static() const { return method()->is_static(); }
virtual void pass_int() = 0;
virtual void pass_long() = 0;
! virtual void pass_object() = 0; // objects, arrays, inlines
virtual void pass_float() = 0;
#ifdef _LP64
virtual void pass_double() = 0;
#else
virtual void pass_double() { pass_long(); } // may be same as long
*** 325,423 ****
const int JNIEnv_words = 1;
const int mirror_words = 1;
_prepended = !is_static() ? JNIEnv_words : JNIEnv_words + mirror_words;
}
! // iterate() calles the 2 virtual methods according to the following invocation syntax:
//
// {pass_int | pass_long | pass_object}
//
// Arguments are handled from left to right (receiver first, if any).
// The offset() values refer to the Java stack offsets but are 0 based and increasing.
// The java_offset() values count down to 0, and refer to the Java TOS.
// The jni_offset() values increase from 1 or 2, and refer to C arguments.
! void iterate() { iterate(Fingerprinter(method()).fingerprint());
! }
!
!
! // Optimized path if we have the bitvector form of signature
! void iterate( uint64_t fingerprint ) {
!
if (!is_static()) {
// handle receiver (not handled by iterate because not in signature)
pass_object(); _jni_offset++; _offset++;
}
!
! SignatureIterator::iterate_parameters( fingerprint );
}
};
! // Handy stream for iterating over signature
class SignatureStream : public StackObj {
private:
! Symbol* _signature;
int _begin;
int _end;
BasicType _type;
! bool _at_return_type;
Symbol* _previous_name; // cache the previously looked up symbol to avoid lookups
GrowableArray<Symbol*>* _names; // symbols created while parsing that need to be dereferenced
! public:
! bool at_return_type() const { return _at_return_type; }
! bool is_done() const;
! void next_non_primitive(int t);
! void next() {
! Symbol* sig = _signature;
! int len = sig->utf8_length();
! if (_end >= len) {
! _end = len + 1;
! return;
! }
!
! _begin = _end;
! int t = sig->char_at(_begin);
! switch (t) {
! case JVM_SIGNATURE_BYTE: _type = T_BYTE; break;
! case JVM_SIGNATURE_CHAR: _type = T_CHAR; break;
! case JVM_SIGNATURE_DOUBLE: _type = T_DOUBLE; break;
! case JVM_SIGNATURE_FLOAT: _type = T_FLOAT; break;
! case JVM_SIGNATURE_INT: _type = T_INT; break;
! case JVM_SIGNATURE_LONG: _type = T_LONG; break;
! case JVM_SIGNATURE_SHORT: _type = T_SHORT; break;
! case JVM_SIGNATURE_BOOLEAN: _type = T_BOOLEAN; break;
! case JVM_SIGNATURE_VOID: _type = T_VOID; break;
! default : next_non_primitive(t);
! return;
! }
! _end++;
}
! SignatureStream(Symbol* signature, bool is_method = true);
~SignatureStream();
! bool is_object() const; // True if this argument is an object
! bool is_array() const; // True if this argument is an array
BasicType type() const { return _type; }
- Symbol* as_symbol();
- enum FailureMode { ReturnNull, NCDFError };
- Klass* as_klass(Handle class_loader, Handle protection_domain, FailureMode failure_mode, TRAPS);
- oop as_java_mirror(Handle class_loader, Handle protection_domain, FailureMode failure_mode, TRAPS);
- const u1* raw_bytes() { return _signature->bytes() + _begin; }
- int raw_length() { return _end - _begin; }
! // return same as_symbol except allocation of new symbols is avoided.
! Symbol* as_symbol_or_null();
! // count the number of references in the signature
! int reference_parameter_count();
};
! #ifdef ASSERT
! class SignatureVerifier : public StackObj {
public:
static bool is_valid_method_signature(Symbol* sig);
static bool is_valid_type_signature(Symbol* sig);
private:
static ssize_t is_valid_type(const char*, ssize_t);
--- 439,584 ----
const int JNIEnv_words = 1;
const int mirror_words = 1;
_prepended = !is_static() ? JNIEnv_words : JNIEnv_words + mirror_words;
}
! void iterate() { iterate(Fingerprinter(method()).fingerprint()); }
!
! // iterate() calls the 3 virtual methods according to the following invocation syntax:
//
// {pass_int | pass_long | pass_object}
//
// Arguments are handled from left to right (receiver first, if any).
// The offset() values refer to the Java stack offsets but are 0 based and increasing.
// The java_offset() values count down to 0, and refer to the Java TOS.
// The jni_offset() values increase from 1 or 2, and refer to C arguments.
+ // The method's return type is ignored.
! void iterate(fingerprint_t fingerprint) {
! set_fingerprint(fingerprint);
if (!is_static()) {
// handle receiver (not handled by iterate because not in signature)
pass_object(); _jni_offset++; _offset++;
}
! do_parameters_on(this);
}
};
! // This is the core parsing logic for iterating over signatures.
! // All of the previous classes use this for doing their work.
class SignatureStream : public StackObj {
private:
! const Symbol* _signature;
int _begin;
int _end;
+ int _limit;
+ int _array_prefix; // count of '[' before the array element descr
BasicType _type;
! int _state;
Symbol* _previous_name; // cache the previously looked up symbol to avoid lookups
GrowableArray<Symbol*>* _names; // symbols created while parsing that need to be dereferenced
!
! inline int scan_non_primitive(BasicType type);
!
! Symbol* find_symbol();
!
! enum { _s_field = 0, _s_method = 1, _s_method_return = 3 };
! void set_done() {
! _state |= -2; // preserve s_method bit
! assert(is_done(), "Unable to set state to done");
}
! public:
! bool is_method_signature() const { return (_state & (int)_s_method) != 0; }
! bool at_return_type() const { return _state == (int)_s_method_return; }
! bool is_done() const { return _state < 0; }
! void next();
!
! SignatureStream(const Symbol* signature, bool is_method = true);
~SignatureStream();
! bool is_reference() const { return is_reference_type(_type); }
! bool is_array() const { return _type == T_ARRAY; }
! bool is_primitive() const { return is_java_primitive(_type); }
BasicType type() const { return _type; }
! const u1* raw_bytes() const { return _signature->bytes() + _begin; }
! int raw_length() const { return _end - _begin; }
! int raw_begin() const { return _begin; }
! int raw_end() const { return _end; }
! int raw_symbol_begin() const { return _begin + (has_envelope() ? 1 : 0); }
! int raw_symbol_end() const { return _end - (has_envelope() ? 1 : 0); }
! char raw_char_at(int i) const {
! assert(i < _limit, "index for raw_char_at is over the limit");
! return _signature->char_at(i);
! }
!
! // True if there is an embedded class name in this type,
! // followed by ';'.
! bool has_envelope() const {
! if (!Signature::has_envelope(_signature->char_at(_begin)))
! return false;
! // this should always be true, but let's test it:
! assert(_signature->char_at(_end-1) == JVM_SIGNATURE_ENDCLASS, "signature envelope has no semi-colon at end");
! return true;
! }
!
! // return the symbol for chars in symbol_begin()..symbol_end()
! Symbol* as_symbol() {
! return find_symbol();
! }
!
! // in case you want only the return type:
! void skip_to_return_type();
!
! // number of '[' in array prefix
! int array_prefix_length() {
! return _type == T_ARRAY ? _array_prefix : 0;
! }
!
! // In case you want only the array base type,
! // reset the stream after skipping some brackets '['.
! // (The argument is clipped to array_prefix_length(),
! // and if it ends up as zero this call is a nop.
! // The default is value skips all brackets '['.)
! int skip_array_prefix(int prefix_length = 9999);
! // free-standing lookups (bring your own CL/PD pair)
! enum FailureMode { ReturnNull, NCDFError, CachedOrNull };
! Klass* as_klass(Handle class_loader, Handle protection_domain, FailureMode failure_mode, TRAPS);
! oop as_java_mirror(Handle class_loader, Handle protection_domain, FailureMode failure_mode, TRAPS);
};
! // Here is how all the SignatureIterator classes invoke the
! // SignatureStream engine to do their parsing.
! template<typename T> inline
! void SignatureIterator::do_parameters_on(T* callback) {
! fingerprint_t unaccumulator = _fingerprint;
!
! // Check for too many arguments, or missing fingerprint:
! if (!fp_is_valid(unaccumulator)) {
! SignatureStream ss(_signature);
! for (; !ss.at_return_type(); ss.next()) {
! callback->do_type(ss.type());
! }
! // while we are here, capture the return type
! _return_type = ss.type();
! } else {
! // Optimized version of do_parameters when fingerprint is known
! assert(_return_type != T_ILLEGAL, "return type already captured from fp");
! unaccumulator = fp_start_parameters(unaccumulator);
! for (BasicType type; (type = fp_next_parameter(unaccumulator)) != (BasicType)fp_parameters_done; ) {
! assert(fp_is_valid_type(type), "garbled fingerprint");
! callback->do_type(type);
! }
! }
! }
!
! #ifdef ASSERT
! class SignatureVerifier : public StackObj {
public:
static bool is_valid_method_signature(Symbol* sig);
static bool is_valid_type_signature(Symbol* sig);
private:
static ssize_t is_valid_type(const char*, ssize_t);
< prev index next >