• 深入jvm虚拟机--第一篇 void TemplateInterpreterGenerator::generate_and_dispatch(Template* t, TosState tos_out) 函数


    今天第一次使用虚拟姐打断点,断点设置在了void TemplateInterpreterGenerator::generate_and_dispatch(Template* t, TosState tos_out) 了

    在TemplateInterpreterGenerator.cpp中,这个函数之前看书就不太懂,现在debug时候就能分析的比较清楚了,这个函数的介绍在解密jvm的528页中有具体介绍

    void TemplateInterpreterGenerator::generate_and_dispatch(Template* t, TosState tos_out) {
      if (PrintBytecodeHistogram)                                    histogram_bytecode(t);
    #ifndef PRODUCT
      // debugging code
      if (CountBytecodes || TraceBytecodes || StopInterpreterAt > 0) count_bytecode();
      if (PrintBytecodePairHistogram)                                histogram_bytecode_pair(t);
      if (TraceBytecodes)                                            trace_bytecode(t);
      if (StopInterpreterAt > 0)                                     stop_interpreter_at();
      __ verify_FPU(1, t->tos_in());
    #endif // !PRODUCT
      int step = 0;
      if (!t->does_dispatch()) {
        step = t->is_wide() ? Bytecodes::wide_length_for(t->bytecode()) : Bytecodes::length_for(t->bytecode());
        if (tos_out == ilgl) tos_out = t->tos_out();
        // compute bytecode size
        assert(step > 0, "just checkin'");
        // setup stuff for dispatching next bytecode
        if (ProfileInterpreter && VerifyDataPointer
            && MethodData::bytecode_has_profile(t->bytecode())) {
          __ verify_method_data_pointer();
        }
        __ dispatch_prolog(tos_out, step);
      }
      // generate template
      t->generate(_masm);
      // advance
      if (t->does_dispatch()) {
    #ifdef ASSERT
        // make sure execution doesn't go beyond this point if code is broken
        __ should_not_reach_here();
    #endif // ASSERT
      } else {
        // dispatch to next bytecode
        __ dispatch_epilog(tos_out, step);
      }
    }

    先看这个入参函数Template

    这个是一个对象,在哪里定义的呢?得往上边查看

    void TemplateInterpreterGenerator::set_entry_points(Bytecodes::Code code) {
      CodeletMark cm(_masm, Bytecodes::name(code), code);
      // initialize entry points
      assert(_unimplemented_bytecode    != NULL, "should have been generated before");
      assert(_illegal_bytecode_sequence != NULL, "should have been generated before");
      address bep = _illegal_bytecode_sequence;
      address zep = _illegal_bytecode_sequence;
      address cep = _illegal_bytecode_sequence;
      address sep = _illegal_bytecode_sequence;
      address aep = _illegal_bytecode_sequence;
      address iep = _illegal_bytecode_sequence;
      address lep = _illegal_bytecode_sequence;
      address fep = _illegal_bytecode_sequence;
      address dep = _illegal_bytecode_sequence;
      address vep = _unimplemented_bytecode;
      address wep = _unimplemented_bytecode;
      // code for short & wide version of bytecode
      if (Bytecodes::is_defined(code)) {
        Template* t = TemplateTable::template_for(code);
        assert(t->is_valid(), "just checking");
        set_short_entry_points(t, bep, cep, sep, aep, iep, lep, fep, dep, vep);
      }
      if (Bytecodes::wide_is_defined(code)) {
        Template* t = TemplateTable::template_for_wide(code);
        assert(t->is_valid(), "just checking");
        set_wide_entry_point(t, wep);
      }
      // set entry points
      EntryPoint entry(bep, zep, cep, sep, aep, iep, lep, fep, dep, vep);
      Interpreter::_normal_table.set_entry(code, entry);
      Interpreter::_wentry_point[code] = wep;
    }

    是通过: Template* t = TemplateTable::template_for(code); 得到的; TemplateTable的定义

    需要知道的是这个是个 静态类,理解是类似于java,能在全局通过类:成员,类:方法来调用(引用)

    class TemplateTable: AllStatic {
     public:
      enum Operation { add, sub, mul, div, rem, _and, _or, _xor, shl, shr, ushr };
      enum Condition { equal, not_equal, less, less_equal, greater, greater_equal };
      enum CacheByte { f1_byte = 1, f2_byte = 2, f1_oop = 0x11 };  // byte_no codes
    
     private:
      static bool            _is_initialized;        // true if TemplateTable has been initialized
      static Template        _template_table     [Bytecodes::number_of_codes];
      static Template        _template_table_wide[Bytecodes::number_of_codes];
    
      static Template*       _desc;                  // the current template to be generated
      static Bytecodes::Code bytecode()              { return _desc->bytecode(); }
    
      static BarrierSet*     _bs;                    // Cache the barrier set.
     public:
      //%note templates_1
      static InterpreterMacroAssembler* _masm;       // the assembler used when generating templates
    
     private:
    
      // special registers
      static inline Address at_bcp(int offset);
    
      // helpers
      static void unimplemented_bc();
      static void patch_bytecode(Bytecodes::Code bc, Register bc_reg,
                                 Register temp_reg, bool load_bc_into_bc_reg = true, int byte_no = -1);
    
      // C calls
      static void call_VM(Register oop_result, address entry_point);
      static void call_VM(Register oop_result, address entry_point, Register arg_1);
      static void call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2);
      static void call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, Register arg_3);
    
      // these overloadings are not presently used on SPARC:
      static void call_VM(Register oop_result, Register last_java_sp, address entry_point);
      static void call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1);
      static void call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2);
      static void call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, Register arg_3);
    
      // bytecodes
      static void nop();
    
      static void aconst_null();
      static void iconst(int value);
      static void lconst(int value);
      static void fconst(int value);
      static void dconst(int value);
    
      static void bipush();
      static void sipush();
      static void ldc(bool wide);
      static void ldc2_w();
      static void fast_aldc(bool wide);
    
      static void locals_index(Register reg, int offset = 1);
      static void iload();
      static void fast_iload();
      static void fast_iload2();
      static void fast_icaload();
      static void lload();
      static void fload();
      static void dload();
      static void aload();
    
      static void locals_index_wide(Register reg);
      static void wide_iload();
      static void wide_lload();
      static void wide_fload();
      static void wide_dload();
      static void wide_aload();
    
      static void iaload();
      static void laload();
      static void faload();
      static void daload();
      static void aaload();
      static void baload();
      static void caload();
      static void saload();
    
      static void iload(int n);
      static void lload(int n);
      static void fload(int n);
      static void dload(int n);
      static void aload(int n);
      static void aload_0();
    
      static void istore();
      static void lstore();
      static void fstore();
      static void dstore();
      static void astore();
    
    
    };

    那么试着摸索  能看到 _template_table,这个是一个数组,一共有239个,对应了239个字节码指令

     static Template* template_for     (Bytecodes::Code code)  { Bytecodes::check     (code); return &_template_table     [code]; }

    此时code值为01则返回对应的为_nop的指令,意思就是t=一个_nop字节码的信息,还接着看

    step = t->is_wide() ? Bytecodes::wide_length_for(t->bytecode()) : Bytecodes::length_for(t->bytecode());

    此为generate_and_dispatch函数中的,分析  t->bytecode(),值==01

    //share/vm/interpreter/templateTable.cpp文件中
    Bytecodes::Code Template::bytecode() const { int i = this - TemplateTable::_template_table; if (i < 0 || i >= Bytecodes::number_of_codes)
         i = this - TemplateTable::_template_table_wide; return Bytecodes::cast(i); }

    那么看_template_table,还是上面已经介绍的那个,接着分析

    Bytecodes::wide_length_for(01)

    这里的用法就是静态方法调用,查看Bytecodes类

    class Bytecodes: AllStatic {
     public:
      enum Code {
        _illegal              =  -1,
    
        // Java bytecodes
        _nop                  =   0, // 0x00
        _aconst_null          =   1, // 0x01
        _iconst_m1            =   2, // 0x02
        _iconst_0             =   3, // 0x03
        _iconst_1             =   4, // 0x04
        _iconst_2             =   5, // 0x05
        _iconst_3             =   6, // 0x06
        _iconst_4             =   7, // 0x07
        _iconst_5             =   8, // 0x08
        _lconst_0             =   9, // 0x09
        _lconst_1             =  10, // 0x0a
        _fconst_0             =  11, // 0x0b
        _fconst_1             =  12, // 0x0c
        _fconst_2             =  13, // 0x0d
        _dconst_0             =  14, // 0x0e
        _dconst_1             =  15, // 0x0f
        _bipush               =  16, // 0x10
        _sipush               =  17, // 0x11
        _ldc                  =  18, // 0x12
        _ldc_w                =  19, // 0x13
        _ldc2_w               =  20, // 0x14
        _iload                =  21, // 0x15
        _lload                =  22, // 0x16
        _fload                =  23, // 0x17
        _dload                =  24, // 0x18
        _aload                =  25, // 0x19
        _iload_0              =  26, // 0x1a
        _iload_1              =  27, // 0x1b
        _iload_2              =  28, // 0x1c
        _iload_3              =  29, // 0x1d
        _lload_0              =  30, // 0x1e
        _lload_1              =  31, // 0x1f
        _lload_2              =  32, // 0x20
        _lload_3              =  33, // 0x21
        _fload_0              =  34, // 0x22
         number_of_codes
      };
    
      // Flag bits derived from format strings, can_trap, can_rewrite, etc.:
      enum Flags {
        // semantic flags:
        _bc_can_trap      = 1<<0,     // bytecode execution can trap or block
        _bc_can_rewrite   = 1<<1,     // bytecode execution has an alternate form
    
        // format bits (determined only by the format string):
        _fmt_has_c        = 1<<2,     // constant, such as sipush "bcc"
        _fmt_has_j        = 1<<3,     // constant pool cache index, such as getfield "bjj"
        _fmt_has_k        = 1<<4,     // constant pool index, such as ldc "bk"
        _fmt_has_i        = 1<<5,     // local index, such as iload
        _fmt_has_o        = 1<<6,     // offset, such as ifeq
        _fmt_has_nbo      = 1<<7,     // contains native-order field(s)
        _fmt_has_u2       = 1<<8,     // contains double-byte field(s)
        _fmt_has_u4       = 1<<9,     // contains quad-byte field
        _fmt_not_variable = 1<<10,    // not of variable length (simple or wide)
        _fmt_not_simple   = 1<<11,    // either wide or variable length
        _all_fmt_bits     = (_fmt_not_simple*2 - _fmt_has_c),
    
        // Example derived format syndromes:
        _fmt_b      = _fmt_not_variable,
        _fmt_bc     = _fmt_b | _fmt_has_c,
        _fmt_bi     = _fmt_b | _fmt_has_i,
        _fmt_bkk    = _fmt_b | _fmt_has_k | _fmt_has_u2,
        _fmt_bJJ    = _fmt_b | _fmt_has_j | _fmt_has_u2 | _fmt_has_nbo,
        _fmt_bo2    = _fmt_b | _fmt_has_o | _fmt_has_u2,
        _fmt_bo4    = _fmt_b | _fmt_has_o | _fmt_has_u4
      };
    
     private:
      static bool        _is_initialized;
      static const char* _name          [number_of_codes];
      static BasicType   _result_type   [number_of_codes];
      static s_char      _depth         [number_of_codes];
      static u_char      _lengths       [number_of_codes];
      static Code        _java_code     [number_of_codes];
      static jchar       _flags         [(1<<BitsPerByte)*2]; // all second page for wide formats
    
      static void        def(Code code, const char* name, const char* format, const char* wide_format, BasicType result_type, int depth, bool can_trap);
      static void        def(Code code, const char* name, const char* format, const char* wide_format, BasicType result_type, int depth, bool can_trap, Code java_code);
      static void        pd_initialize();              // platform specific initialization
      static Code        pd_base_code_for(Code code);  // platform specific base_code_for implementation
    
      // Verify that bcp points into method
    #ifdef ASSERT
      static bool        check_method(const methodOopDesc* method, address bcp);
    #endif
      static bool check_must_rewrite(Bytecodes::Code bc);
    
     public:
      // Conversion
      static void        check          (Code code)    { assert(is_defined(code), "illegal code"); }
      static void        wide_check     (Code code)    { assert(wide_is_defined(code), "illegal code"); }
      static Code        cast           (int  code)    { return (Code)code; }
    
      static Code       code_at(const methodOopDesc* method, address bcp) {
        assert(method == NULL || check_method(method, bcp), "bcp must point into method");
        Code code = cast(*bcp);
        assert(code != _breakpoint || method != NULL, "need methodOop to decode breakpoint");
        return (code != _breakpoint) ? code : non_breakpoint_code_at(method, bcp);
      }
      static Code       java_code_at(const methodOopDesc* method, address bcp) {
        return java_code(code_at(method, bcp));
      }
    
      // Fetch a bytecode or a breakpoint:
      static Code       code_or_bp_at(address bcp)    { return (Code)cast(*bcp); }
    
      static Code       code_at(methodOop method, int bci);
      static bool       is_active_breakpoint_at(address bcp) { return (Code)*bcp == _breakpoint; }
    
      // find a bytecode, behind a breakpoint if necessary:
      static Code       non_breakpoint_code_at(const methodOopDesc* method, address bcp);
    
      // Bytecode attributes
      static bool        is_defined     (int  code)    { return 0 <= code && code < number_of_codes && flags(code, false) != 0; }
      static bool        wide_is_defined(int  code)    { return is_defined(code) && flags(code, true) != 0; }
      static const char* name           (Code code)    { check(code);      return _name          [code]; }
      static BasicType   result_type    (Code code)    { check(code);      return _result_type   [code]; }
      static int         depth          (Code code)    { check(code);      return _depth         [code]; }
      // Note: Length functions must return <=0 for invalid bytecodes.
      // Calling check(code) in length functions would throw an unwanted assert.
      static int         length_for     (Code code)    { /*no check*/      return _lengths       [code] & 0xF; }
      static int         wide_length_for(Code code)    { /*no check*/      return _lengths       [code] >> 4; }
      static bool        can_trap       (Code code)    { check(code);      return has_all_flags(code, _bc_can_trap, false); }
      static Code        java_code      (Code code)    { check(code);      return _java_code     [code]; }
      static bool        can_rewrite    (Code code)    { check(code);      return has_all_flags(code, _bc_can_rewrite, false); }
      static bool        must_rewrite(Bytecodes::Code code) { return can_rewrite(code) && check_must_rewrite(code); }
      static bool        native_byte_order(Code code)  { check(code);      return has_all_flags(code, _fmt_has_nbo, false); }
      static bool        uses_cp_cache  (Code code)    { check(code);      return has_all_flags(code, _fmt_has_j, false); }
      // if 'end' is provided, it indicates the end of the code buffer which
      // should not be read past when parsing.
      static int         special_length_at(Bytecodes::Code code, address bcp, address end = NULL);
      static int         special_length_at(methodOop method, address bcp, address end = NULL) { return special_length_at(code_at(method, bcp), bcp, end); }
      static int         raw_special_length_at(address bcp, address end = NULL);
      static int         length_for_code_at(Bytecodes::Code code, address bcp)  { int l = length_for(code); return l > 0 ? l : special_length_at(code, bcp); }
      static int         length_at      (methodOop method, address bcp)  { return length_for_code_at(code_at(method, bcp), bcp); }
      static int         java_length_at (methodOop method, address bcp)  { return length_for_code_at(java_code_at(method, bcp), bcp); }
      static bool        is_java_code   (Code code)    { return 0 <= code && code < number_of_java_codes; }
    
      static bool        is_aload       (Code code)    { return (code == _aload  || code == _aload_0  || code == _aload_1
                                                                                 || code == _aload_2  || code == _aload_3); }
      static bool        is_astore      (Code code)    { return (code == _astore || code == _astore_0 || code == _astore_1
                                                                                 || code == _astore_2 || code == _astore_3); }
    
      static bool        is_zero_const  (Code code)    { return (code == _aconst_null || code == _iconst_0
                                                               || code == _fconst_0 || code == _dconst_0); }
      static bool        is_invoke      (Code code)    { return (_invokevirtual <= code && code <= _invokedynamic); }
    
      static int         compute_flags  (const char* format, int more_flags = 0);  // compute the flags
      static int         flags          (int code, bool is_wide) {
        assert(code == (u_char)code, "must be a byte");
        return _flags[code + (is_wide ? (1<<BitsPerByte) : 0)];
      }
      static int         format_bits    (Code code, bool is_wide) { return flags(code, is_wide) & _all_fmt_bits; }
      static bool        has_all_flags  (Code code, int test_flags, bool is_wide) {
        return (flags(code, is_wide) & test_flags) == test_flags;
      }
    
      // Initialization
      static void        initialize     ();
    };
    
    #endif // SHARE_VM_INTERPRETER_BYTECODES_HPP

    那么

    static int         wide_length_for(Code code)    { /*no check*/      return _lengths       [code] >> 4; }

    这个静态类中的值

    那么久能看到了 _lengths[01] 为1,
     static int         length_for     (Code code)    { /*no check*/      return _lengths       [code] & 0xF; }
    _lengths[01]为1 &1111111 还是为1;

    今天先分析到这里,明天再续
    现在准备执行
      // generate template
      t->generate(_masm);

    还是要看Template这个东西,先看类的定义

    //"interpreter/interpreterRuntime.hpp"
    class Template VALUE_OBJ_CLASS_SPEC {
     private:
      enum Flags {
        uses_bcp_bit,                                // set if template needs the bcp pointing to bytecode
        does_dispatch_bit,                           // set if template dispatches on its own
        calls_vm_bit,                                // set if template calls the vm
        wide_bit                                     // set if template belongs to a wide instruction
      };
    
      typedef void (*generator)(int arg);
    
      int       _flags;                              // describes interpreter template properties (bcp unknown)
      TosState  _tos_in;                             // tos cache state before template execution
      TosState  _tos_out;                            // tos cache state after  template execution
      generator _gen;                                // template code generator
      int       _arg;                                // argument for template code generator
    
      void      initialize(int flags, TosState tos_in, TosState tos_out, generator gen, int arg);
    
      friend class TemplateTable;
    
     public:
      Bytecodes::Code bytecode() const;
      bool      is_valid() const                     { return _gen != NULL; }
      bool      uses_bcp() const                     { return (_flags & (1 << uses_bcp_bit     )) != 0; }
      bool      does_dispatch() const                { return (_flags & (1 << does_dispatch_bit)) != 0; }
      bool      calls_vm() const                     { return (_flags & (1 << calls_vm_bit     )) != 0; }
      bool      is_wide() const                      { return (_flags & (1 << wide_bit         )) != 0; }
      TosState  tos_in() const                       { return _tos_in; }
      TosState  tos_out() const                      { return _tos_out; }
      void      generate(InterpreterMacroAssembler* masm);
    };

    //进入函数内部

    void Template::generate(InterpreterMacroAssembler* masm) {
      // parameter passing
      TemplateTable::_desc = this;
      TemplateTable::_masm = masm;
      // code generation
      _gen(_arg);  ///这个函数在 TemplateTable类中
      masm->flush();
    }

    进入_gen(_arg)

    //templateTable_x86.cpp
    void TemplateTable::nop() {
      transition(vtos, vtos);
      // nothing to do
    }

    这里正是对应了templateTable

    特别注意上边的类的调用: Template::generater ===>调用了 TemplateTable::nop函数

    这nop函数啥也没做

    void TemplateTable::transition(TosState tos_in, TosState tos_out) {
      assert(_desc->tos_in()  == tos_in , "inconsistent tos_in  information");
      assert(_desc->tos_out() == tos_out, "inconsistent tos_out information");
    }

    这样就结束了,  t->generate(_masm);生成模板的函数调用,之前看过template是 在哪里 Template                   TemplateTable::_template_table     [Bytecodes::number_of_codes];保存

    那么他是怎么创造的呢?

    //templateTable.cpp
    void
    TemplateTable::initialize() { if (_is_initialized) return; // Initialize table TraceTime timer("TemplateTable initialization", TraceStartupTime); _bs = Universe::heap()->barrier_set(); // For better readability const char _ = ' '; const int ____ = 0; const int ubcp = 1 << Template::uses_bcp_bit; const int disp = 1 << Template::does_dispatch_bit; const int clvm = 1 << Template::calls_vm_bit; const int iswd = 1 << Template::wide_bit; // interpr. templates // Java spec bytecodes ubcp|disp|clvm|iswd in out generator argument def(Bytecodes::_nop , ____|____|____|____, vtos, vtos, nop , _ ); def(Bytecodes::_aconst_null , ____|____|____|____, vtos, atos, aconst_null , _ ); def(Bytecodes::_iconst_m1 , ____|____|____|____, vtos, itos, iconst , -1 ); def(Bytecodes::_iconst_0 , ____|____|____|____, vtos, itos, iconst , 0 ); def(Bytecodes::_iconst_1 , ____|____|____|____, vtos, itos, iconst , 1 ); def(Bytecodes::_iconst_2 , ____|____|____|____, vtos, itos, iconst , 2 ); def(Bytecodes::_iconst_3 , ____|____|____|____, vtos, itos, iconst , 3 ); def(Bytecodes::_iconst_4 , ____|____|____|____, vtos, itos, iconst , 4 ); def(Bytecodes::_iconst_5 , ____|____|____|____, vtos, itos, iconst , 5 ); def(Bytecodes::_lconst_0 , ____|____|____|____, vtos, ltos, lconst , 0 ); def(Bytecodes::_lconst_1 , ____|____|____|____, vtos, ltos, lconst , 1 ); def(Bytecodes::_fconst_0 , ____|____|____|____, vtos, ftos, fconst , 0 ); def(Bytecodes::_fconst_1 , ____|____|____|____, vtos, ftos, fconst , 1 ); def(Bytecodes::_fconst_2 , ____|____|____|____, vtos, ftos, fconst , 2 ); def(Bytecodes::_dconst_0 , ____|____|____|____, vtos, dtos, dconst , 0 ); def(Bytecodes::_dconst_1 , ____|____|____|____, vtos, dtos, dconst , 1 ); def(Bytecodes::_bipush , ubcp|____|____|____, vtos, itos, bipush , _ ); def(Bytecodes::_sipush , ubcp|____|____|____, vtos, itos, sipush , _ ); def(Bytecodes::_ldc , ubcp|____|clvm|____, vtos, vtos, ldc , false ); def(Bytecodes::_ldc_w , ubcp|____|clvm|____, vtos, vtos, ldc , true ); def(Bytecodes::_ldc2_w , ubcp|____|____|____, vtos, vtos, ldc2_w , _ ); def(Bytecodes::_iload , ubcp|____|clvm|____, vtos, itos, iload , _ ); def(Bytecodes::_lload , ubcp|____|____|____, vtos, ltos, lload , _ ); def(Bytecodes::_fload , ubcp|____|____|____, vtos, ftos, fload , _ ); def(Bytecodes::_dload , ubcp|____|____|____, vtos, dtos, dload , _ ); def(Bytecodes::_aload , ubcp|____|clvm|____, vtos, atos, aload , _ ); def(Bytecodes::_iload_0 , ____|____|____|____, vtos, itos, iload , 0 ); def(Bytecodes::_iload_1 , ____|____|____|____, vtos, itos, iload , 1 ); def(Bytecodes::_iload_2 , ____|____|____|____, vtos, itos, iload , 2 ); def(Bytecodes::_iload_3 , ____|____|____|____, vtos, itos, iload , 3 ); def(Bytecodes::_lload_0 , ____|____|____|____, vtos, ltos, lload , 0 ); def(Bytecodes::_lload_1 , ____|____|____|____, vtos, ltos, lload , 1 ); def(Bytecodes::_lload_2 , ____|____|____|____, vtos, ltos, lload , 2 ); def(Bytecodes::_lload_3 , ____|____|____|____, vtos, ltos, lload , 3 ); def(Bytecodes::_fload_0 , ____|____|____|____, vtos, ftos, fload , 0 ); def(Bytecodes::_fload_1 , ____|____|____|____, vtos, ftos, fload , 1 ); def(Bytecodes::_fload_2 , ____|____|____|____, vtos, ftos, fload , 2 ); def(Bytecodes::_fload_3 , ____|____|____|____, vtos, ftos, fload , 3 ); def(Bytecodes::_dload_0 , ____|____|____|____, vtos, dtos, dload , 0 ); def(Bytecodes::_dload_1 , ____|____|____|____, vtos, dtos, dload , 1 ); def(Bytecodes::_dload_2 , ____|____|____|____, vtos, dtos, dload , 2 ); def(Bytecodes::_dload_3 , ____|____|____|____, vtos, dtos, dload , 3 ); def(Bytecodes::_aload_0 , ubcp|____|clvm|____, vtos, atos, aload_0 , _ ); def(Bytecodes::_aload_1 , ____|____|____|____, vtos, atos, aload , 1 ); def(Bytecodes::_aload_2 , ____|____|____|____, vtos, atos, aload , 2 ); def(Bytecodes::_aload_3 , ____|____|____|____, vtos, atos, aload , 3 ); def(Bytecodes::_iaload , ____|____|____|____, itos, itos, iaload , _ ); def(Bytecodes::_laload , ____|____|____|____, itos, ltos, laload , _ ); def(Bytecodes::_faload , ____|____|____|____, itos, ftos, faload , _ ); def(Bytecodes::_daload , ____|____|____|____, itos, dtos, daload , _ ); def(Bytecodes::_aaload , ____|____|____|____, itos, atos, aaload , _ ); def(Bytecodes::_baload , ____|____|____|____, itos, itos, baload , _ ); def(Bytecodes::_caload , ____|____|____|____, itos, itos, caload , _ ); def(Bytecodes::_saload , ____|____|____|____, itos, itos, saload , _ ); def(Bytecodes::_istore , ubcp|____|clvm|____, itos, vtos, istore , _ ); def(Bytecodes::_lstore , ubcp|____|____|____, ltos, vtos, lstore , _ ); def(Bytecodes::_fstore , ubcp|____|____|____, ftos, vtos, fstore , _ ); def(Bytecodes::_dstore , ubcp|____|____|____, dtos, vtos, dstore , _ ); def(Bytecodes::_astore , ubcp|____|clvm|____, vtos, vtos, astore , _ ); def(Bytecodes::_istore_0 , ____|____|____|____, itos, vtos, istore , 0 ); def(Bytecodes::_istore_1 , ____|____|____|____, itos, vtos, istore , 1 ); def(Bytecodes::_istore_2 , ____|____|____|____, itos, vtos, istore , 2 ); def(Bytecodes::_istore_3 , ____|____|____|____, itos, vtos, istore , 3 ); def(Bytecodes::_lstore_0 , ____|____|____|____, ltos, vtos, lstore , 0 ); def(Bytecodes::_lstore_1 , ____|____|____|____, ltos, vtos, lstore , 1 ); def(Bytecodes::_lstore_2 , ____|____|____|____, ltos, vtos, lstore , 2 ); def(Bytecodes::_lstore_3 , ____|____|____|____, ltos, vtos, lstore , 3 ); def(Bytecodes::_fstore_0 , ____|____|____|____, ftos, vtos, fstore , 0 ); def(Bytecodes::_fstore_1 , ____|____|____|____, ftos, vtos, fstore , 1 ); def(Bytecodes::_fstore_2 , ____|____|____|____, ftos, vtos, fstore , 2 ); def(Bytecodes::_fstore_3 , ____|____|____|____, ftos, vtos, fstore , 3 ); def(Bytecodes::_dstore_0 , ____|____|____|____, dtos, vtos, dstore , 0 ); def(Bytecodes::_dstore_1 , ____|____|____|____, dtos, vtos, dstore , 1 ); def(Bytecodes::_dstore_2 , ____|____|____|____, dtos, vtos, dstore , 2 ); def(Bytecodes::_dstore_3 , ____|____|____|____, dtos, vtos, dstore , 3 ); def(Bytecodes::_astore_0 , ____|____|____|____, vtos, vtos, astore , 0 ); def(Bytecodes::_astore_1 , ____|____|____|____, vtos, vtos, astore , 1 ); def(Bytecodes::_astore_2 , ____|____|____|____, vtos, vtos, astore , 2 ); def(Bytecodes::_astore_3 , ____|____|____|____, vtos, vtos, astore , 3 ); def(Bytecodes::_iastore , ____|____|____|____, itos, vtos, iastore , _ ); def(Bytecodes::_lastore , ____|____|____|____, ltos, vtos, lastore , _ ); def(Bytecodes::_fastore , ____|____|____|____, ftos, vtos, fastore , _ ); def(Bytecodes::_dastore , ____|____|____|____, dtos, vtos, dastore , _ ); def(Bytecodes::_aastore , ____|____|clvm|____, vtos, vtos, aastore , _ ); def(Bytecodes::_bastore , ____|____|____|____, itos, vtos, bastore , _ ); def(Bytecodes::_castore , ____|____|____|____, itos, vtos, castore , _ ); def(Bytecodes::_sastore , ____|____|____|____, itos, vtos, sastore , _ ); def(Bytecodes::_pop , ____|____|____|____, vtos, vtos, pop , _ ); def(Bytecodes::_pop2 , ____|____|____|____, vtos, vtos, pop2 , _ ); def(Bytecodes::_dup , ____|____|____|____, vtos, vtos, dup , _ ); def(Bytecodes::_dup_x1 , ____|____|____|____, vtos, vtos, dup_x1 , _ ); def(Bytecodes::_dup_x2 , ____|____|____|____, vtos, vtos, dup_x2 , _ ); def(Bytecodes::_dup2 , ____|____|____|____, vtos, vtos, dup2 , _ ); def(Bytecodes::_dup2_x1 , ____|____|____|____, vtos, vtos, dup2_x1 , _ ); def(Bytecodes::_dup2_x2 , ____|____|____|____, vtos, vtos, dup2_x2 , _ ); def(Bytecodes::_swap , ____|____|____|____, vtos, vtos, swap , _ ); def(Bytecodes::_iadd , ____|____|____|____, itos, itos, iop2 , add ); def(Bytecodes::_ladd , ____|____|____|____, ltos, ltos, lop2 , add ); def(Bytecodes::_fadd , ____|____|____|____, ftos, ftos, fop2 , add ); def(Bytecodes::_dadd , ____|____|____|____, dtos, dtos, dop2 , add ); def(Bytecodes::_isub , ____|____|____|____, itos, itos, iop2 , sub ); def(Bytecodes::_lsub , ____|____|____|____, ltos, ltos, lop2 , sub ); def(Bytecodes::_fsub , ____|____|____|____, ftos, ftos, fop2 , sub ); def(Bytecodes::_dsub , ____|____|____|____, dtos, dtos, dop2 , sub ); def(Bytecodes::_imul , ____|____|____|____, itos, itos, iop2 , mul ); def(Bytecodes::_lmul , ____|____|____|____, ltos, ltos, lmul , _ ); def(Bytecodes::_fmul , ____|____|____|____, ftos, ftos, fop2 , mul ); def(Bytecodes::_dmul , ____|____|____|____, dtos, dtos, dop2 , mul ); def(Bytecodes::_idiv , ____|____|____|____, itos, itos, idiv , _ ); def(Bytecodes::_ldiv , ____|____|____|____, ltos, ltos, ldiv , _ ); def(Bytecodes::_fdiv , ____|____|____|____, ftos, ftos, fop2 , div ); def(Bytecodes::_ddiv , ____|____|____|____, dtos, dtos, dop2 , div ); def(Bytecodes::_irem , ____|____|____|____, itos, itos, irem , _ ); def(Bytecodes::_lrem , ____|____|____|____, ltos, ltos, lrem , _ ); def(Bytecodes::_frem , ____|____|____|____, ftos, ftos, fop2 , rem ); def(Bytecodes::_drem , ____|____|____|____, dtos, dtos, dop2 , rem ); def(Bytecodes::_ineg , ____|____|____|____, itos, itos, ineg , _ ); def(Bytecodes::_lneg , ____|____|____|____, ltos, ltos, lneg , _ ); def(Bytecodes::_fneg , ____|____|____|____, ftos, ftos, fneg , _ ); def(Bytecodes::_dneg , ____|____|____|____, dtos, dtos, dneg , _ ); def(Bytecodes::_ishl , ____|____|____|____, itos, itos, iop2 , shl ); def(Bytecodes::_lshl , ____|____|____|____, itos, ltos, lshl , _ ); def(Bytecodes::_ishr , ____|____|____|____, itos, itos, iop2 , shr ); def(Bytecodes::_lshr , ____|____|____|____, itos, ltos, lshr , _ ); def(Bytecodes::_iushr , ____|____|____|____, itos, itos, iop2 , ushr ); def(Bytecodes::_lushr , ____|____|____|____, itos, ltos, lushr , _ ); def(Bytecodes::_iand , ____|____|____|____, itos, itos, iop2 , _and ); def(Bytecodes::_land , ____|____|____|____, ltos, ltos, lop2 , _and ); def(Bytecodes::_ior , ____|____|____|____, itos, itos, iop2 , _or ); def(Bytecodes::_lor , ____|____|____|____, ltos, ltos, lop2 , _or ); def(Bytecodes::_ixor , ____|____|____|____, itos, itos, iop2 , _xor ); def(Bytecodes::_lxor , ____|____|____|____, ltos, ltos, lop2 , _xor ); def(Bytecodes::_iinc , ubcp|____|clvm|____, vtos, vtos, iinc , _ ); def(Bytecodes::_i2l , ____|____|____|____, itos, ltos, convert , _ ); def(Bytecodes::_i2f , ____|____|____|____, itos, ftos, convert , _ ); def(Bytecodes::_i2d , ____|____|____|____, itos, dtos, convert , _ ); def(Bytecodes::_l2i , ____|____|____|____, ltos, itos, convert , _ ); def(Bytecodes::_l2f , ____|____|____|____, ltos, ftos, convert , _ ); def(Bytecodes::_l2d , ____|____|____|____, ltos, dtos, convert , _ ); def(Bytecodes::_f2i , ____|____|____|____, ftos, itos, convert , _ ); def(Bytecodes::_f2l , ____|____|____|____, ftos, ltos, convert , _ ); def(Bytecodes::_f2d , ____|____|____|____, ftos, dtos, convert , _ ); def(Bytecodes::_d2i , ____|____|____|____, dtos, itos, convert , _ ); def(Bytecodes::_d2l , ____|____|____|____, dtos, ltos, convert , _ ); def(Bytecodes::_d2f , ____|____|____|____, dtos, ftos, convert , _ ); def(Bytecodes::_i2b , ____|____|____|____, itos, itos, convert , _ ); def(Bytecodes::_i2c , ____|____|____|____, itos, itos, convert , _ ); def(Bytecodes::_i2s , ____|____|____|____, itos, itos, convert , _ ); def(Bytecodes::_lcmp , ____|____|____|____, ltos, itos, lcmp , _ ); def(Bytecodes::_fcmpl , ____|____|____|____, ftos, itos, float_cmp , -1 ); def(Bytecodes::_fcmpg , ____|____|____|____, ftos, itos, float_cmp , 1 ); def(Bytecodes::_dcmpl , ____|____|____|____, dtos, itos, double_cmp , -1 ); def(Bytecodes::_dcmpg , ____|____|____|____, dtos, itos, double_cmp , 1 ); def(Bytecodes::_ifeq , ubcp|____|clvm|____, itos, vtos, if_0cmp , equal ); def(Bytecodes::_ifne , ubcp|____|clvm|____, itos, vtos, if_0cmp , not_equal ); def(Bytecodes::_iflt , ubcp|____|clvm|____, itos, vtos, if_0cmp , less ); def(Bytecodes::_ifge , ubcp|____|clvm|____, itos, vtos, if_0cmp , greater_equal); def(Bytecodes::_ifgt , ubcp|____|clvm|____, itos, vtos, if_0cmp , greater ); def(Bytecodes::_ifle , ubcp|____|clvm|____, itos, vtos, if_0cmp , less_equal ); def(Bytecodes::_if_icmpeq , ubcp|____|clvm|____, itos, vtos, if_icmp , equal ); def(Bytecodes::_if_icmpne , ubcp|____|clvm|____, itos, vtos, if_icmp , not_equal ); def(Bytecodes::_if_icmplt , ubcp|____|clvm|____, itos, vtos, if_icmp , less ); def(Bytecodes::_if_icmpge , ubcp|____|clvm|____, itos, vtos, if_icmp , greater_equal); def(Bytecodes::_if_icmpgt , ubcp|____|clvm|____, itos, vtos, if_icmp , greater ); def(Bytecodes::_if_icmple , ubcp|____|clvm|____, itos, vtos, if_icmp , less_equal ); def(Bytecodes::_if_acmpeq , ubcp|____|clvm|____, atos, vtos, if_acmp , equal ); def(Bytecodes::_if_acmpne , ubcp|____|clvm|____, atos, vtos, if_acmp , not_equal ); def(Bytecodes::_goto , ubcp|disp|clvm|____, vtos, vtos, _goto , _ ); def(Bytecodes::_jsr , ubcp|disp|____|____, vtos, vtos, jsr , _ ); // result is not an oop, so do not transition to atos def(Bytecodes::_ret , ubcp|disp|____|____, vtos, vtos, ret , _ ); def(Bytecodes::_tableswitch , ubcp|disp|____|____, itos, vtos, tableswitch , _ ); def(Bytecodes::_lookupswitch , ubcp|disp|____|____, itos, itos, lookupswitch , _ ); def(Bytecodes::_ireturn , ____|disp|clvm|____, itos, itos, _return , itos ); def(Bytecodes::_lreturn , ____|disp|clvm|____, ltos, ltos, _return , ltos ); def(Bytecodes::_freturn , ____|disp|clvm|____, ftos, ftos, _return , ftos ); def(Bytecodes::_dreturn , ____|disp|clvm|____, dtos, dtos, _return , dtos ); def(Bytecodes::_areturn , ____|disp|clvm|____, atos, atos, _return , atos ); def(Bytecodes::_return , ____|disp|clvm|____, vtos, vtos, _return , vtos ); def(Bytecodes::_getstatic , ubcp|____|clvm|____, vtos, vtos, getstatic , f1_byte ); def(Bytecodes::_putstatic , ubcp|____|clvm|____, vtos, vtos, putstatic , f2_byte ); def(Bytecodes::_getfield , ubcp|____|clvm|____, vtos, vtos, getfield , f1_byte ); def(Bytecodes::_putfield , ubcp|____|clvm|____, vtos, vtos, putfield , f2_byte ); def(Bytecodes::_invokevirtual , ubcp|disp|clvm|____, vtos, vtos, invokevirtual , f2_byte ); def(Bytecodes::_invokespecial , ubcp|disp|clvm|____, vtos, vtos, invokespecial , f1_byte ); def(Bytecodes::_invokestatic , ubcp|disp|clvm|____, vtos, vtos, invokestatic , f1_byte ); def(Bytecodes::_invokeinterface , ubcp|disp|clvm|____, vtos, vtos, invokeinterface , f1_byte ); def(Bytecodes::_invokedynamic , ubcp|disp|clvm|____, vtos, vtos, invokedynamic , f1_oop ); def(Bytecodes::_new , ubcp|____|clvm|____, vtos, atos, _new , _ ); def(Bytecodes::_newarray , ubcp|____|clvm|____, itos, atos, newarray , _ ); def(Bytecodes::_anewarray , ubcp|____|clvm|____, itos, atos, anewarray , _ ); def(Bytecodes::_arraylength , ____|____|____|____, atos, itos, arraylength , _ ); def(Bytecodes::_athrow , ____|disp|____|____, atos, vtos, athrow , _ ); def(Bytecodes::_checkcast , ubcp|____|clvm|____, atos, atos, checkcast , _ ); def(Bytecodes::_instanceof , ubcp|____|clvm|____, atos, itos, instanceof , _ ); def(Bytecodes::_monitorenter , ____|disp|clvm|____, atos, vtos, monitorenter , _ ); def(Bytecodes::_monitorexit , ____|____|clvm|____, atos, vtos, monitorexit , _ ); def(Bytecodes::_wide , ubcp|disp|____|____, vtos, vtos, wide , _ ); def(Bytecodes::_multianewarray , ubcp|____|clvm|____, vtos, atos, multianewarray , _ ); def(Bytecodes::_ifnull , ubcp|____|clvm|____, atos, vtos, if_nullcmp , equal ); def(Bytecodes::_ifnonnull , ubcp|____|clvm|____, atos, vtos, if_nullcmp , not_equal ); def(Bytecodes::_goto_w , ubcp|____|clvm|____, vtos, vtos, goto_w , _ ); def(Bytecodes::_jsr_w , ubcp|____|____|____, vtos, vtos, jsr_w , _ ); // wide Java spec bytecodes def(Bytecodes::_iload , ubcp|____|____|iswd, vtos, itos, wide_iload , _ ); def(Bytecodes::_lload , ubcp|____|____|iswd, vtos, ltos, wide_lload , _ ); def(Bytecodes::_fload , ubcp|____|____|iswd, vtos, ftos, wide_fload , _ ); def(Bytecodes::_dload , ubcp|____|____|iswd, vtos, dtos, wide_dload , _ ); def(Bytecodes::_aload , ubcp|____|____|iswd, vtos, atos, wide_aload , _ ); def(Bytecodes::_istore , ubcp|____|____|iswd, vtos, vtos, wide_istore , _ ); def(Bytecodes::_lstore , ubcp|____|____|iswd, vtos, vtos, wide_lstore , _ ); def(Bytecodes::_fstore , ubcp|____|____|iswd, vtos, vtos, wide_fstore , _ ); def(Bytecodes::_dstore , ubcp|____|____|iswd, vtos, vtos, wide_dstore , _ ); def(Bytecodes::_astore , ubcp|____|____|iswd, vtos, vtos, wide_astore , _ ); def(Bytecodes::_iinc , ubcp|____|____|iswd, vtos, vtos, wide_iinc , _ ); def(Bytecodes::_ret , ubcp|disp|____|iswd, vtos, vtos, wide_ret , _ ); def(Bytecodes::_breakpoint , ubcp|disp|clvm|____, vtos, vtos, _breakpoint , _ ); // JVM bytecodes def(Bytecodes::_fast_agetfield , ubcp|____|____|____, atos, atos, fast_accessfield , atos ); def(Bytecodes::_fast_bgetfield , ubcp|____|____|____, atos, itos, fast_accessfield , itos ); def(Bytecodes::_fast_cgetfield , ubcp|____|____|____, atos, itos, fast_accessfield , itos ); def(Bytecodes::_fast_dgetfield , ubcp|____|____|____, atos, dtos, fast_accessfield , dtos ); def(Bytecodes::_fast_fgetfield , ubcp|____|____|____, atos, ftos, fast_accessfield , ftos ); def(Bytecodes::_fast_igetfield , ubcp|____|____|____, atos, itos, fast_accessfield , itos ); def(Bytecodes::_fast_lgetfield , ubcp|____|____|____, atos, ltos, fast_accessfield , ltos ); def(Bytecodes::_fast_sgetfield , ubcp|____|____|____, atos, itos, fast_accessfield , itos ); def(Bytecodes::_fast_aputfield , ubcp|____|____|____, atos, vtos, fast_storefield , atos ); def(Bytecodes::_fast_bputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos ); def(Bytecodes::_fast_zputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos ); def(Bytecodes::_fast_cputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos ); def(Bytecodes::_fast_dputfield , ubcp|____|____|____, dtos, vtos, fast_storefield , dtos ); def(Bytecodes::_fast_fputfield , ubcp|____|____|____, ftos, vtos, fast_storefield , ftos ); def(Bytecodes::_fast_iputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos ); def(Bytecodes::_fast_lputfield , ubcp|____|____|____, ltos, vtos, fast_storefield , ltos ); def(Bytecodes::_fast_sputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos ); def(Bytecodes::_fast_aload_0 , ____|____|____|____, vtos, atos, aload , 0 ); def(Bytecodes::_fast_iaccess_0 , ubcp|____|____|____, vtos, itos, fast_xaccess , itos ); def(Bytecodes::_fast_aaccess_0 , ubcp|____|____|____, vtos, atos, fast_xaccess , atos ); def(Bytecodes::_fast_faccess_0 , ubcp|____|____|____, vtos, ftos, fast_xaccess , ftos ); def(Bytecodes::_fast_iload , ubcp|____|____|____, vtos, itos, fast_iload , _ ); def(Bytecodes::_fast_iload2 , ubcp|____|____|____, vtos, itos, fast_iload2 , _ ); def(Bytecodes::_fast_icaload , ubcp|____|____|____, vtos, itos, fast_icaload , _ ); def(Bytecodes::_fast_invokevfinal , ubcp|disp|clvm|____, vtos, vtos, fast_invokevfinal , f2_byte ); def(Bytecodes::_fast_linearswitch , ubcp|disp|____|____, itos, vtos, fast_linearswitch , _ ); def(Bytecodes::_fast_binaryswitch , ubcp|disp|____|____, itos, vtos, fast_binaryswitch , _ ); def(Bytecodes::_fast_aldc , ubcp|____|clvm|____, vtos, atos, fast_aldc , false ); def(Bytecodes::_fast_aldc_w , ubcp|____|clvm|____, vtos, atos, fast_aldc , true ); def(Bytecodes::_return_register_finalizer , ____|disp|clvm|____, vtos, vtos, _return , vtos ); def(Bytecodes::_shouldnotreachhere , ____|____|____|____, vtos, vtos, shouldnotreachhere , _ ); // platform specific bytecodes pd_initialize(); _is_initialized = true; }

    看这个函数:TemplateTable::initialize(),这里为每个字节码指令进行了一次def(....)命令,

     def(Bytecodes::_nop                 , ____|____|____|____, vtos, vtos, nop                 ,  _           );

    def就是定义的意思,关注这个nop参数,他是一个函数位于templateTable.cpp

    void TemplateTable::nop() {
      transition(vtos, vtos);
      // nothing to do
    }

    看def函数

    void TemplateTable::def(Bytecodes::Code code, int flags, TosState in, TosState out, void (*gen)(int arg), int arg) {
      // should factor out these constants
      const int ubcp = 1 << Template::uses_bcp_bit;
      const int disp = 1 << Template::does_dispatch_bit;
      const int clvm = 1 << Template::calls_vm_bit;
      const int iswd = 1 << Template::wide_bit;
      // determine which table to use
      bool is_wide = (flags & iswd) != 0;
      // make sure that wide instructions have a vtos entry point
      // (since they are executed extremely rarely, it doesn't pay out to have an
      // extra set of 5 dispatch tables for the wide instructions - for simplicity
      // they all go with one table)
      assert(in == vtos || !is_wide, "wide instructions have vtos entry point only");
      Template* t = is_wide ? template_for_wide(code) : template_for(code);
      // setup entry
      t->initialize(flags, in, out, gen, arg);
      assert(t->bytecode() == code, "just checkin'");
    }

    关键点就在 Template* t = is_wide ? template_for_wide(code) : template_for(code);

    之前分析过t=? : template_for(code);是在 static Template        _template_table [];数组中保存的

    那么这句话就是获取一个得到数组中的一个引用,应该这个t不能是null,否则就会空指针异常了,应该在哪里初始化过了,那么接下了

    生成具体内容 t->initialize(flags, in, out, gen, arg);

    // Implementation of Template
    
    
    void Template::initialize(int flags, TosState tos_in, TosState tos_out, generator gen, int arg) {
      _flags   = flags;
      _tos_in  = tos_in;
      _tos_out = tos_out;
      _gen     = gen;
      _arg     = arg;
    }

    也没干别的就是把 templateTable中的函数指针,数据等赋值给了 Template对象(模板对象)

    接着分析 dispatch_epilog(tos_out, step);

    __ dispatch_epilog 其中的开头__ 代表 masm 这在揭秘虚拟机中有解释,

    void InterpreterMacroAssembler::dispatch_epilog(TosState state, int step) {
      dispatch_next(state, step);
    }
    void InterpreterMacroAssembler::dispatch_next(TosState state, int step, bool generate_poll) {
      // load next bytecode (load before advancing _bcp_register to prevent AGI)
      load_unsigned_byte(rbx, Address(_bcp_register, step));
      // advance _bcp_register
      increment(_bcp_register, step);
      dispatch_base(state, Interpreter::dispatch_table(state), true, generate_poll);
    }

    对应的

    那么今天就结束了,下次再续





  • 相关阅读:
    hbase 学习笔记一---基本概念
    hdu 4496 (并差集)
    rqnoj-105-核电站问题-dp
    面试之BI-SQL--table转换
    Android:从程序员到架构师之路Ⅲ_高焕堂
    Linux 的进程组、会话、守护进程
    Oracle创建dblink报错:ORA-01017、ORA-02063解决
    JSP 指令
    JSP 生命周期
    JSP 结构
  • 原文地址:https://www.cnblogs.com/zytcomeon/p/14514563.html
Copyright © 2020-2023  润新知