これらは, Java の型を表す文字列(Signature String)を扱うためのユーティリティ・クラス. より具体的に言うと, Signature String に対して iterate 処理するためのイテレータクラス.
(なお Signature String とは "[Lfoo;D)I" みたいな文字列のこと)
Java の型を表す文字列(Signature String)に対して iterate 処理するための一時オブジェクト(ResourceObjクラス) (の基底クラス).
なお, このクラス自体は abstract class であり, 実際に使われるのはサブクラス.
((cite: hotspot/src/share/vm/runtime/signature.hpp))
class SignatureIterator: public ResourceObj {
使用する際には, (iterate 処理で呼び出される) do_int() メソッドや do_array() メソッド等をオーバーライドしたサブクラスを作ればいい.
((cite: hotspot/src/share/vm/runtime/signature.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().
See: here for details
SignatureIterator クラスのサブクラスの1つ.
このクラスは, Signature String 中の各型の型名(を表す文字列)に対して何らかの処理を行う場合用.
なお, このクラス自体は abstract class であり, 実際に使われるのはサブクラス.
((cite: hotspot/src/share/vm/runtime/signature.hpp))
// Specialized SignatureIterators: Used to compute signature specific values.
class SignatureTypeNames : public SignatureIterator {
使用する際には, type_name() メソッドをオーバーライドしたサブクラスを作ればいい.
((cite: hotspot/src/share/vm/runtime/signature.hpp))
virtual void type_name(const char* name) = 0;
各 do_*() メソッドでは, その型名を表す文字列を引数として type_name() が呼び出される.
((cite: hotspot/src/share/vm/runtime/signature.hpp))
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" ); }
今のところ SignatureTypeNames のサブクラスはこいつだけ (しかもこいつは #ifndef PRODUCT でないと定義されないデバッグ用(開発時用)のクラス...).
((cite: hotspot/src/share/vm/oops/methodOop.cpp))
#ifndef PRODUCT
class SignatureTypePrinter : public SignatureTypeNames {
See: here for details
SignatureIterator クラスのサブクラスの1つ.
このクラスは, Signature String 中の各型(を表す定数)およびその型のサイズ情報に対して何らかの処理を行う場合用.
なお, このクラス自体は abstract class であり, 実際に使われるのはサブクラス.
((cite: hotspot/src/share/vm/runtime/signature.hpp))
class SignatureInfo: public SignatureIterator {
使用する際には, set() メソッドをオーバーライドしたサブクラスを作ればいい.
((cite: hotspot/src/share/vm/runtime/signature.hpp))
virtual void set(int size, BasicType type) = 0;
各 do_*() メソッドでは, その型を表す定数と型の大きさを引数として set() が呼び出される.
((cite: hotspot/src/share/vm/runtime/signature.hpp))
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 ); }
See: here for details
SignatureInfo クラスの具象サブクラスの1つ.
メソッド型を表す Signature String を渡すと, 引数の合計サイズを計算してくれる.
((cite: hotspot/src/share/vm/runtime/signature.hpp))
// Specialized SignatureIterator: Used to compute the argument size.
class ArgumentSizeComputer: public SignatureInfo {
(なお局所変数の宣言が煩わしければ, コンストラクタからメソッドチェインして size(), という荒技も可能)
HotSpot 内の様々な箇所で使用されている (#TODO).
See: here for details
SignatureInfo クラスの具象サブクラスの1つ.
メソッド型を表す Signature String を渡すと, 引数の個数を計算してくれる.
((cite: hotspot/src/share/vm/runtime/signature.hpp))
class ArgumentCount: public SignatureInfo {
(なお局所変数の宣言が煩わしければ, コンストラクタからメソッドチェインして size(), という手もある. というか, ArgumentSizeComputer とは逆で, ArgumentCount の場合はこちらの用法の方が圧倒的に多い. 似たようなクラスなのに何故違う??)
HotSpot 内の様々な箇所で使用されている (#TODO).
See: here for details
SignatureInfo クラスの具象サブクラスの1つ.
メソッド型を表す Signature String を渡すと, 返値の型を取得してくれる.
((cite: hotspot/src/share/vm/runtime/signature.hpp))
// Specialized SignatureIterator: Used to compute the result type.
class ResultTypeFinder: public SignatureInfo {
(なお局所変数の宣言が煩わしければ, コンストラクタからメソッドチェインして type(), も出来るはずだがこのクラスでは行われていない)
以下の箇所で(のみ)使用されている.
See: here for details
SignatureIterator クラスの具象サブクラスの1つ.
メソッド型を表す Signature String を渡すと, それに対するハッシュ値(finger print)を計算してくれる.
((cite: hotspot/src/share/vm/runtime/signature.hpp))
// 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 {
(なお局所変数の宣言が煩わしければ, コンストラクタからメソッドチェインして fingerprint(), という手もある. というか, 正確に言うとこのクラスの場合はこの用法しかない (局所変数を宣言している箇所はない))
以下の箇所で(のみ)使用されている.
((cite: hotspot/src/share/vm/interpreter/interpreterRuntime.cpp))
void SignatureHandlerLibrary::add(methodHandle method) {
...
if (UseFastSignatureHandlers && method->size_of_parameters() <= Fingerprinter::max_size_of_parameters) {
...
// lookup method signature's fingerprint
uint64_t fingerprint = Fingerprinter(method).fingerprint();
(...そういえば ResourceObj だったな. new してる箇所が他にないから忘れてたが...)
((cite: hotspot/src/share/vm/prims/jni.cpp))
static void jni_invoke_static(JNIEnv *env, JavaValue* result, jobject receiver, JNICallType call_type, jmethodID method_id, JNI_ArgumentPusher *args, TRAPS) {
...
// Fill out JavaCallArguments object
args->iterate( Fingerprinter(method).fingerprint() );
((cite: hotspot/src/share/vm/prims/jni.cpp))
static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receiver, JNICallType call_type, jmethodID method_id, JNI_ArgumentPusher *args, TRAPS) {
...
// Fill out JavaCallArguments object
args->iterate( Fingerprinter(method).fingerprint() );
ハッシュ値の作成方法は「型に応じた定数(大きさはそれぞれ parameter_feature_size ビット)を引数の順に並べる」という単純なもの.
なお parameter_feature_size の値は現在は 4. ハッシュ値の大きさは 64bit (uint64_t) なので, 内部に含まれる型が 16 個以下であれば一意な finger print になることが保証される.
((cite: hotspot/src/share/vm/runtime/signature.hpp))
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(); }
See: here for details
SignatureIterator クラスのサブクラスの1つ.
なお, このクラス自体は abstract class であり, 実際に使われるのはサブクラス.
それぞれの型に応じて pass_int(), pass_double(), pass_object() 等のメソッドが呼ばれる他, それらの型のサイズを _offset フィールドと _jni_offset フィールドに累積していく.
なお型の取り扱いは JVM 上での扱い方に合わせており, bool や char が pass_int() に引き渡されたり, long や double の場合は _offset が2つ増えたりする.
((cite: hotspot/src/share/vm/runtime/signature.hpp))
// Specialized SignatureIterator: Used for native call purposes
class NativeSignatureIterator: public SignatureIterator {
使用する際には, pass_*() メソッドをオーバーライドしたサブクラスを作ればいい.
((cite: hotspot/src/share/vm/runtime/signature.hpp))
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
#endif
各 do_() メソッドでは, 対応する pass_() メソッドを呼んだ後, _offset フィールドと _jni_offset フィールドを適切に増加させる.
((cite: hotspot/src/share/vm/runtime/signature.hpp))
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++; }
なお, _offset フィールドと _jni_offset フィールドは, それぞれ以下のような値を格納するフィールド.
((cite: hotspot/src/share/vm/runtime/signature.hpp))
// We need separate JNI and Java offset values because in 64 bit mode,
// the argument offsets are not in sync with the Java stack.
// 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
See: here for details
Java の型を表す文字列(Signature String)中の各型をたどるためのイテレータクラス(StackObjクラス).
なお, SignatureIterator は内部イテレータだが, こちらは外部イテレータ. SignatureIterator のようにサブクラスを作ってメソッドをオーバーライドするという使い方ではなく, next() メソッドで次の要素を追っていく.
((cite: hotspot/src/share/vm/runtime/signature.hpp))
// Handy stream for iterating over signature
class SignatureStream : public StackObj {
実際に使用する際にはこんな感じになる.
((cite: hotspot/src/share/vm/code/nmethod.cpp))
for (SignatureStream ss(m->signature()); !ss.at_return_type(); ss.next()) {
BasicType t = ss.type();
...
}
HotSpot 内の様々な箇所で使用されている (#TODO).
See: here for details
ClassVerifier クラス内で使用される補助クラス.
型を表す文字列 (Signature String) が正しいかどうかを判定する関数を納めた名前空間 (このクラスは AllStatic ではないが (というか何故か StackObj になっているが) static な定義しか持たない).
((cite: hotspot/src/share/vm/runtime/signature.hpp))
class SignatureVerifier : public StackObj {
以下の箇所で(のみ)使用されている.
定義されている public メソッドは, 以下の通り.
(なお, is_valid_signature() は現状どこからも使用されていない)
((cite: hotspot/src/share/vm/runtime/signature.hpp))
public:
// Returns true if the symbol is valid method or type signature
static bool is_valid_signature(Symbol* sig);
static bool is_valid_method_signature(Symbol* sig);
static bool is_valid_type_signature(Symbol* sig);
See: here for details
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.