Пример #1
0
Method* Class::_resolve_method(Global_Env* env, unsigned cp_index)
{
    lock();
    if(m_const_pool.is_entry_in_error(cp_index)) {
        TRACE2("resolve.testing", "Constant pool entry " << cp_index << " already contains error.");
        unlock();
        return NULL;
    }

#ifdef ORDER
    if(m_const_pool.is_entry_resolved(cp_index, this)) {//ORDER
        unlock();
        return m_const_pool.get_ref_method(cp_index);
    }
#else
    if(m_const_pool.is_entry_resolved(cp_index)) {//ORDER
        unlock();
        return m_const_pool.get_ref_method(cp_index);
    }
#endif

    //
    // constant pool entry hasn't been resolved yet
    //
    unsigned other_index;
    other_index = m_const_pool.get_ref_class_index(cp_index);
    unlock();

    //
    // check error condition from resolve class
    //
    Class* other_clss = _resolve_class(env, other_index);
    if(!other_clss) {
        if(m_const_pool.is_entry_in_error(other_index)) {
            class_report_failure(this, cp_index, 
                m_const_pool.get_error_cause(other_index));
        } else {
            assert(exn_raised());
        }
        return NULL;
    }

    uint16 name_and_type_index = m_const_pool.get_ref_name_and_type_index(cp_index);
    String* name = m_const_pool.get_name_and_type_name(name_and_type_index);
    String* desc = m_const_pool.get_name_and_type_descriptor(name_and_type_index);

    // CONSTANT_Methodref must refer to a class, not an interface, and
    // CONSTANT_InterfaceMethodref must refer to an interface (vm spec 4.4.2)
    if(m_const_pool.is_methodref(cp_index) && other_clss->is_interface()) {
        CLASS_REPORT_FAILURE(this, cp_index, "java/lang/IncompatibleClassChangeError",
            other_clss->get_name()->bytes
            << " while resolving constant pool entry " << cp_index
            << " in class " << m_name->bytes);
        return NULL;
    }

    if(m_const_pool.is_interfacemethodref(cp_index) && !other_clss->is_interface()) {
        CLASS_REPORT_FAILURE(this, cp_index, "java/lang/IncompatibleClassChangeError",
            other_clss->get_name()->bytes
            << " while resolving constant pool entry " << cp_index
            << " in class " << m_name->bytes);
        return NULL;
    }

    Method* method = class_lookup_method_recursive(other_clss, name, desc);
    if(method == NULL) {
        // NoSuchMethodError
        CLASS_REPORT_FAILURE(this, cp_index, "java/lang/NoSuchMethodError",
            other_clss->get_name()->bytes << "." << name->bytes << desc->bytes
            << " while resolving constant pool entry at index " << cp_index
            << " in class " << m_name->bytes);
        return NULL;
    }

    if(method->is_abstract() && !other_clss->is_abstract()) {
        // AbstractMethodError
        CLASS_REPORT_FAILURE(this, cp_index, "java/lang/AbstractMethodError",
            other_clss->get_name()->bytes << "." << name->bytes << desc->bytes
            << " while resolving constant pool entry at index " << cp_index
            << " in class " << m_name->bytes);
        return NULL;
    }

    //
    // check access permissions
    //
    if(!can_access_member(method)) {
        // IllegalAccessError
        CLASS_REPORT_FAILURE(this, cp_index, "java/lang/IllegalAccessError",
            other_clss->get_name()->bytes << "." << name->bytes << desc->bytes
            << " while resolving constant pool entry at index " << cp_index
            << " in class " << m_name->bytes);
        return NULL; 
    }

    lock();
    m_const_pool.resolve_entry(cp_index, method);
    unlock();

    return method;
} //_resolve_method
Пример #2
0
Class* Class::resolve_declaring_class(Global_Env* env)
{
    if(m_declaring_class_index == 0) return NULL;
    return _resolve_class(env, m_declaring_class_index);
}
Пример #3
0
Field* Class::_resolve_field(Global_Env *env, unsigned cp_index)
{
    lock();
    if(m_const_pool.is_entry_in_error(cp_index)) {
        TRACE2("resolve.testing", "Constant pool entry " << cp_index << " already contains error.");
        unlock();
        return NULL;
    }

#ifdef ORDER
    if(m_const_pool.is_entry_resolved(cp_index, this)) {//ORDER
        unlock();
        return m_const_pool.get_ref_field(cp_index);
    }
#else
    if(m_const_pool.is_entry_resolved(cp_index)) {
        unlock();
        return m_const_pool.get_ref_field(cp_index);
    }
#endif

    //
    // constant pool entry hasn't been resolved yet
    //
    unsigned other_index = m_const_pool.get_ref_class_index(cp_index);
    unlock();

    //
    // check error condition from resolve class
    //
    Class* other_clss = _resolve_class(env, other_index);
    if(!other_clss) {
        if(m_const_pool.is_entry_in_error(other_index)) {
            class_report_failure(this, cp_index,
                m_const_pool.get_error_cause(other_index));
        } else {
            assert(exn_raised());
        }
        return NULL;
    }

    uint16 name_and_type_index = m_const_pool.get_ref_name_and_type_index(cp_index);
    String* name = m_const_pool.get_name_and_type_name(name_and_type_index);
    String* desc = m_const_pool.get_name_and_type_descriptor(name_and_type_index);
    Field* field = other_clss->lookup_field_recursive(name, desc);
    if(field == NULL)
    {
        //
        // NoSuchFieldError
        //
        CLASS_REPORT_FAILURE(this, cp_index, "java/lang/NoSuchFieldError",
            other_clss->get_name()->bytes << "." << name->bytes
            << " of type " << desc->bytes
            << " while resolving constant pool entry at index "
            << cp_index << " in class " << get_name()->bytes);
        return NULL;
    }

    //
    // check access permissions
    //
    if(!can_access_member(field))
    {
        //
        // IllegalAccessError
        //
        CLASS_REPORT_FAILURE(this, cp_index, "java/lang/IllegalAccessError",
            other_clss->get_name()->bytes << "." << name->bytes
            << " of type " << desc->bytes
            << " while resolving constant pool entry at index "
            << cp_index << " in class " << get_name()->bytes);
        return NULL;
    }
    lock();
    m_const_pool.resolve_entry(cp_index, field);
    unlock();

    return field;
} // Class::_resolve_field