Skip to content

runtime interp invokedynamic_params

ceragon edited this page Jun 23, 2022 · 2 revisions

invokeDynamic params

参数的初始化

class ConstantPoolCache: public MetaspaceObj {
    OopHandle            _resolved_references;
    Array<u2>*           _reference_map;
    void set_resolved_references(OopHandle s) {
        _resolved_references = s; 
    }
};

调用过程

class ConstantPool : public Metadata {
    ConstantPoolCache*   _cache;
    void set_resolved_references(OopHandle s) {
        _cache->set_resolved_references(s); 
    }
};
void ConstantPool::initialize_resolved_references(ClassLoaderData* loader_data,
                                                  const intStack& reference_map,
                                                  int constant_pool_map_length,
                                                  TRAPS) {
    // Initialized the resolved object cache.
    int map_length = reference_map.length();
    if (map_length > 0) {
        objArrayOop stom = oopFactory::new_objArray(SystemDictionary::Object_klass(), map_length, CHECK);
        Handle refs_handle (THREAD, (oop)stom);
        set_resolved_references(loader_data->add_handle(refs_handle));
    }
}
void Rewriter::make_constant_pool_cache(TRAPS) {
    ClassLoaderData* loader_data = _pool->pool_holder()->class_loader_data();
    ConstantPoolCache* cache =
          ConstantPoolCache::allocate(loader_data, _cp_cache_map,
                                  _invokedynamic_cp_cache_map,
                                  _invokedynamic_references_map, CHECK);
    // 互相引用
    _pool->set_cache(cache);
    cache->set_constant_pool(_pool());
    
    _pool->initialize_resolved_references(loader_data, _resolved_references_map,
                                        _resolved_reference_limit,
                                        THREAD);
}
class Rewriter: public StackObj {
    InstanceKlass*      _klass;
    constantPoolHandle  _pool;
    Array<Method*>*     _methods;
    GrowableArray<int>  _cp_cache_map;  // for Methodref, Fieldref,
                                      // InterfaceMethodref and InvokeDynamic
    GrowableArray<int>  _reference_map; // maps from cp index to resolved_refs index (or -1)
    GrowableArray<int>  _resolved_references_map; // for strings, methodHandle, methodType
    GrowableArray<int>  _invokedynamic_references_map; // for invokedynamic resolved refs
    GrowableArray<int>  _method_handle_invokers;
    int                 _resolved_reference_limit;
    GrowableArray<int>      _invokedynamic_cp_cache_map;
};
Rewriter::Rewriter(InstanceKlass* klass, const constantPoolHandle& cpool, Array<Method*>* methods, TRAPS)
        :_klass(klass),
        _pool(cpool),
        _methods(methods),
        _cp_cache_map(initial_size: cpool->length() / 2),
        _invokedynamic_references_map(initial_size: cpool->length() / 2),
        _invokedynamic_cp_cache_map(initial_size: cpool->length() / 4) {
    rewrite_bytecodes(CHECK);
    make_constant_pool_cache(THREAD);
}
void Rewriter::rewrite(InstanceKlass* klass, TRAPS) {
    Rewriter     rw(klass, klass->constants(), klass->methods(), CHECK);
}
void InstanceKlass::rewrite_class(TRAPS) {
    Rewriter::rewrite(this, CHECK);
}

由此可知,当链接一个类的时候,就会触发上面的逻辑

bool InstanceKlass::link_class_impl(bool throw_verifyerror, TRAPS) {
    if (!is_linked()) {
        if (!is_rewritten()) {
            if (is_linked()) {
                return true;
            }
            rewrite_class(CHECK_false);
        }
    }
}

参数的赋值

void Rewriter::rewrite_invokedynamic(address bcp, int offset, bool reverse) {
    // bcp 字节码的地址
    // p 字节码后面参数的地址
    address p = bcp + offset;
    if (!reverse) {
        // 从参数的地址中取出 参数
        int cp_index = Bytes::get_Java_u2(p);
        // cp_index 是 invokeDynamic 指令后面的参数,同时也是个常量池的索引
        
        // cache_index 
        int cache_index = add_invokedynamic_cp_cache_entry(cp_index);
        int resolved_index = add_invokedynamic_resolved_references_entries(cp_index, cache_index);
        // 一种修正
        Bytes::put_native_u4(p, ConstantPool::encode_invokedynamic_index(cache_index));
        // 也就是说 bcp 和 ref 是一一对应的
        _patch_invokedynamic_bcps->push(p);
        _patch_invokedynamic_refs->push(resolved_index);
    }
}

class Rewriter: public StackObj {
    GrowableArray<int>      _invokedynamic_cp_cache_map;
    GrowableArray<int>      _invokedynamic_references_map;
    int add_invokedynamic_cp_cache_entry(int cp_index) {
        int cache_index = _invokedynamic_cp_cache_map.append(cp_index);
        return cache_index + _first_iteration_cp_cache_limit;
    }
    int add_invokedynamic_resolved_references_entries(int cp_index, int cache_index) {
        int ref_index = -1;
        for (int entry = 0; entry < ConstantPoolCacheEntry::_indy_resolved_references_entries; entry++) {
            const int index = _resolved_references_map.append(cp_index);
            if (entry == 0) {
                ref_index = index;
            }
            _invokedynamic_references_map.at_put_grow(index, cache_index, -1);
        }
        return ref_index;
    }
};

Clone this wiki locally