Exemplo n.º 1
0
void class_throw_linking_error(Class_Handle ch, unsigned index, unsigned opcode)
{
    ASSERT_RAISE_AREA;
    tmn_suspend_enable();

    ConstantPool& cp = ch->get_constant_pool();
    if(cp.is_entry_in_error(index)) {
        exn_raise_object(cp.get_error_cause(index));
        tmn_suspend_disable();
        return; // will return in interpreter mode
    }

    switch(opcode) {
        case OPCODE_NEW:
            class_can_instantiate(cp.get_class_class(index), LINK_THROW_ERRORS);
            break;
        case OPCODE_PUTFIELD:
            field_can_link(ch, cp.get_ref_field(index),
                CAN_LINK_FROM_FIELD, LINK_WRITE_ACCESS, LINK_THROW_ERRORS);
            break;
        case OPCODE_GETFIELD:
            field_can_link(ch, cp.get_ref_field(index),
                CAN_LINK_FROM_FIELD, LINK_READ_ACCESS, LINK_THROW_ERRORS);
            break;
        case OPCODE_PUTSTATIC:
            field_can_link(ch, cp.get_ref_field(index),
                CAN_LINK_FROM_STATIC, LINK_WRITE_ACCESS, LINK_THROW_ERRORS);
            break;
        case OPCODE_GETSTATIC:
            field_can_link(ch, cp.get_ref_field(index),
                CAN_LINK_FROM_STATIC, LINK_READ_ACCESS, LINK_THROW_ERRORS);
            break;
        case OPCODE_INVOKEINTERFACE:
            method_can_link_interface(ch, index, cp.get_ref_method(index),
                LINK_THROW_ERRORS);
            break;
        case OPCODE_INVOKESPECIAL:
            method_can_link_special(ch, index, cp.get_ref_method(index),
                LINK_THROW_ERRORS);
            break;
        case OPCODE_INVOKESTATIC:
            method_can_link_static(ch, index, cp.get_ref_method(index),
                LINK_THROW_ERRORS);
            break;
        case OPCODE_INVOKEVIRTUAL:
            method_can_link_virtual(ch, index, cp.get_ref_method(index),
                LINK_THROW_ERRORS);
            break;
        default:
            // FIXME Potentially this can be any RuntimeException or Error
            // The most probable case is OutOfMemoryError.
            LWARN(5, "**Java exception occured during resolution under compilation");
            exn_raise_object(VM_Global_State::loader_env->java_lang_OutOfMemoryError);
            //ASSERT(0, "Unexpected opcode: " << opcode);
            break;
    }
    tmn_suspend_disable();
}
Exemplo n.º 2
0
bool field_can_link(Class* clss, Field* field, bool _static, bool putfield, bool _throw)
{
    ASSERT_RAISE_AREA;
    if(_static?(!field->is_static()):(field->is_static())) {
        if(_throw) {
            exn_raise_by_name("java/lang/IncompatibleClassChangeError",
                field->get_class()->get_name()->bytes);
        }
        return false;
    }
    if(putfield && field->is_final()) {
        for(int fn = 0; fn < clss->get_number_of_fields(); fn++) {
            if(clss->get_field(fn) == field) {
                return true;
            }
        }
        if(_throw) {
            unsigned buf_size = clss->get_name()->len +
                field->get_class()->get_name()->len +
                field->get_name()->len + 15;
            char* buf = (char*)STD_ALLOCA(buf_size);
            memset(buf, 0, buf_size);
            sprintf(buf, " from %s to %s.%s", clss->get_name()->bytes,
                field->get_class()->get_name()->bytes,
                field->get_name()->bytes);
            jthrowable exc_object = exn_create("java/lang/IllegalAccessError", buf);
            exn_raise_object(exc_object);
        }
        return false;
    }
    return true;
}
Exemplo n.º 3
0
//
// resolve constant pool reference to a method
// used for invokespecial
//
Method* resolve_special_method_env(Global_Env *env,
                                    Class_Handle curr_clss,
                                    unsigned index,
                                    bool raise_exn)
{
    ASSERT_RAISE_AREA;

    Method* method = curr_clss->_resolve_method(env, index);
    if(!method) {
        assert(curr_clss->get_constant_pool().is_entry_in_error(index));
        if (raise_exn) {
            exn_raise_object(curr_clss->get_constant_pool().get_error_cause(index));
        }
        return NULL;
    }
    if(curr_clss->is_super()
        && is_class_extended_class(curr_clss->get_super_class(), method->get_class())
        && method->get_name() != env->Init_String)
    {
        Method* result_meth;
        for(Class* clss = curr_clss->get_super_class(); clss; clss = clss->get_super_class())
        {
            result_meth = clss->lookup_method(method->get_name(), method->get_descriptor());
            if(result_meth) {
                method = result_meth;
                break;
            }
        }
    }
    if(method && !method_can_link_special(curr_clss, index, method, raise_exn))
        return NULL;
    return method;
} //resolve_special_method_env
Exemplo n.º 4
0
VMEXPORT // temporary solution for interpreter unplug
Vector_Handle vm_new_vector_primitive(Class *vector_class, int length) {
    ASSERT_RAISE_AREA;
    assert(!hythread_is_suspend_enabled());
    assert(vector_class->is_array_of_primitives());
    unsigned sz = vector_class->calculate_array_size(length);

    if (sz == 0) {
        tmn_suspend_enable();
        if (length < 0) {
            exn_raise_by_name("java/lang/NegativeArraySizeException");
        } else {
            exn_raise_by_name("java/lang/OutOfMemoryError",
                    "VM doesn't support arrays of the requested size");
        }
        tmn_suspend_disable();
        return NULL;
    }

    Vector_Handle vector = (Vector_Handle)gc_alloc(sz, 
        vector_class->get_allocation_handle(), vm_get_gc_thread_local());
#ifdef VM_STATS
    vector_class->instance_allocated(sz);
#endif //VM_STATS

    if (NULL == vector) {
        exn_raise_object(
            VM_Global_State::loader_env->java_lang_OutOfMemoryError);
        return 0;
    }

    set_vector_length(vector, length);
    assert(get_vector_vtable(vector) == vector_class->get_vtable());
    return vector;
}
Exemplo n.º 5
0
void interp_throw_exception(const char* exc_name, const char* exc_message) {
    M2N_ALLOC_MACRO;
    assert(!hythread_is_suspend_enabled());
    hythread_suspend_enable();
    assert(hythread_is_suspend_enabled());
    jthrowable exc_object = exn_create(exc_name, exc_message);
    exn_raise_object(exc_object);
    hythread_suspend_disable();
    M2N_FREE_MACRO;
}
Exemplo n.º 6
0
Class_Handle type_info_get_class_no_exn(Type_Info_Handle tih)
{
    // Store raised exception
    jthrowable exc_object = exn_get();
    // Workaround to let JIT invoke class loader even if exception is pending
    exn_clear();
    Class_Handle ch = type_info_get_class(tih);
    // To clear exn_class if set
    exn_clear();
    // Restore saved exception
    if (exc_object)
        exn_raise_object(exc_object);

    return ch;
} // type_info_get_class_no_exn
static Method* prepare_exc_creating(Class* exc_class, jvalue* args,
    const char* exc_message, jthrowable exc_cause) {
    ASSERT_RAISE_AREA;
    assert(hythread_is_suspend_enabled());

    // Checks that it's corresponding method
    if (NULL == exc_message) {
        return prepare_exc_creating(exc_class, args, exc_cause);
    }

    // Checks that it's corresponding method
    if (NULL == exc_cause) {
        return prepare_exc_creating(exc_class, args, exc_message);
    }

    // Finds corresponding constructor
    Method* exc_init = lookup_exc_constructor(exc_class, "(Ljava/lang/String;Ljava/lang/Throwable;)V");

    // Check that constructor is found
    if (NULL == exc_init){
        return NULL;
    }

    // Creates string object
    tmn_suspend_disable_recursive();

    ManagedObject *arg_obj =
        string_create_from_utf8(exc_message, (unsigned) strlen(exc_message));

    if (!arg_obj) {
        exn_raise_object(VM_Global_State::loader_env->java_lang_OutOfMemoryError);
        return NULL;
    }
    jobject arg = oh_allocate_local_handle();
    arg->object = arg_obj;

    tmn_suspend_enable_recursive();

    // Fills arguments for constructor
    args[1].l = arg;
    args[2].l = exc_cause;

    // Returns found constructor
    return exc_init;
}
Exemplo n.º 8
0
Method* resolve_interface_method_env(Global_Env *env,
                                    Class *clss,
                                    unsigned cp_index, 
                                    bool raise_exn)
 {
    Method* method = clss->_resolve_method(env, cp_index);
    if (!method) {
        assert(clss->get_constant_pool().is_entry_in_error(cp_index));
        if (raise_exn) {
            exn_raise_object(clss->get_constant_pool().get_error_cause(cp_index));
        }
        return NULL;
     }
    if (!method_can_link_interface(clss, cp_index, method, raise_exn)) {
        return NULL;
    }
    return method;
}
Exemplo n.º 9
0
static bool method_can_link_special(Class* clss, unsigned index, Method* method, bool _throw)
{
    ASSERT_RAISE_AREA;

    ConstantPool& cp = clss->get_constant_pool();
    unsigned class_idx = cp.get_ref_class_index(index);
    unsigned class_name_idx = cp.get_class_name_index(class_idx);
    String* ref_class_name = cp.get_utf8_string(class_name_idx);

    if(method->get_name() == VM_Global_State::loader_env->Init_String
        && method->get_class()->get_name() != ref_class_name)
    {
        if(_throw) {
            exn_raise_by_name("java/lang/NoSuchMethodError",
                method->get_name()->bytes);
        }
        return false;
    }
    if(method->is_static())
    {
        if(_throw) {
            exn_raise_by_name("java/lang/IncompatibleClassChangeError",
                method->get_class()->get_name()->bytes);
        }
        return false;
    }
    if(method->is_abstract())
    {
        if(_throw) {
            tmn_suspend_enable();
            unsigned buf_size = clss->get_name()->len +
                method->get_name()->len + method->get_descriptor()->len + 5;
            char* buf = (char*)STD_ALLOCA(buf_size);
            memset(buf, 0, buf_size);
            sprintf(buf, "%s.%s%s", clss->get_name()->bytes,
                method->get_name()->bytes, method->get_descriptor()->bytes);
            jthrowable exc_object = exn_create("java/lang/AbstractMethodError", buf);
            exn_raise_object(exc_object);
            tmn_suspend_disable();
        }
        return false;
    }
    return true;
}
Exemplo n.º 10
0
IDATA jthread_throw_exception_object(jobject object)
{
    if (interpreter_enabled()) {
        // FIXME - Function set_current_thread_exception does the same
        // actions as exn_raise_object, and it should be replaced.
        hythread_suspend_disable();
        set_current_thread_exception(object->object);
        hythread_suspend_enable();
    } else {
        if (is_unwindable()) {
            exn_throw_object(object);
        } else {
            ASSERT_RAISE_AREA;
            exn_raise_object(object);
        }
    }

    return 0;
}
Exemplo n.º 11
0
static Vector_Handle vm_anewarray_resolved_array_type(Class *arr_clss, int length)
{
#ifdef VM_STATS
    UNSAFE_REGION_START
    VM_Statistics::get_vm_stats().num_anewarray++;  
    UNSAFE_REGION_END
#endif
    ASSERT_RAISE_AREA;
    assert(!hythread_is_suspend_enabled());
    assert(!arr_clss->is_array_of_primitives());

    unsigned sz = arr_clss->calculate_array_size(length);
    if (sz == 0) {
        tmn_suspend_enable();

        if (length < 0) {
            exn_raise_by_name("java/lang/NegativeArraySizeException");
        } else {
            exn_raise_by_name("java/lang/OutOfMemoryError",
                    "VM doesn't support arrays of the requested size");
        }
        tmn_suspend_disable();
        return NULL;
    }

    assert((sz & NEXT_TO_HIGH_BIT_SET_MASK) == 0);

    Vector_Handle object_array = (Vector_Handle )gc_alloc(sz,
        arr_clss->get_allocation_handle(), vm_get_gc_thread_local());
#ifdef VM_STATS
    arr_clss->instance_allocated(sz);
#endif //VM_STATS

    if (NULL == object_array) {
        exn_raise_object(
            VM_Global_State::loader_env->java_lang_OutOfMemoryError);
        return NULL;
    }

    set_vector_length(object_array, length);
    assert(get_vector_vtable(object_array) == arr_clss->get_vtable());
    return object_array;
} //vm_anewarray_resolved_array_type
Exemplo n.º 12
0
/*
* Class:     java_lang_VMClassRegistry
* Method:    getEnclosingClass
* Signature: (Ljava/lang/Class;)Ljava/lang/Class;
*/
JNIEXPORT jclass JNICALL Java_java_lang_VMClassRegistry_getEnclosingClass
(JNIEnv *, jclass, jclass jclazz)
{
    assert(jclazz);
    Class* clazz = jclass_to_struct_Class(jclazz);
    unsigned idx = clazz->get_enclosing_class_index();
    if (!idx) {
        idx = clazz->get_declaring_class_index();
    }
    if (idx) {
        Class* outer_clss = clazz->_resolve_class(VM_Global_State::loader_env, idx);
        if (outer_clss) {
            return struct_Class_to_jclass(outer_clss);
        }
        if (!exn_raised()) {
            exn_raise_object(clazz->get_constant_pool().get_error_cause(idx));
        }
    } 
    return NULL;
}
Exemplo n.º 13
0
Field* resolve_nonstatic_field_env(Global_Env* env,
                                    Class* clss,
                                    unsigned cp_index,
                                    unsigned putfield, 
                                    bool raise_exn)
 {
     ASSERT_RAISE_AREA;
 
    Field *field = clss->_resolve_field(env, cp_index);
    if(!field) {
        assert(clss->get_constant_pool().is_entry_in_error(cp_index));
        if (raise_exn) {
            exn_raise_object(clss->get_constant_pool().get_error_cause(cp_index));
        }
        return NULL;
    }
    if(!field_can_link(clss, field, CAN_LINK_FROM_FIELD, putfield, raise_exn)) {
        return NULL;
    }
    return field;
 } 
Exemplo n.º 14
0
/*
* Class:     java_lang_VMClassRegistry
* Method:    getEnclosingMember
* Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Member;
*/
JNIEXPORT jobject JNICALL Java_java_lang_VMClassRegistry_getEnclosingMember
(JNIEnv *jenv, jclass, jclass jclazz)
{
    assert(jclazz);
    Class* clazz = jclass_to_struct_Class(jclazz);
    unsigned method_idx = clazz->get_enclosing_method_index();
    if (method_idx) {
        unsigned c_idx = clazz->get_enclosing_class_index();
        ASSERT(c_idx, ("No class for enclosing method"));
        Class* outer_clss = clazz->_resolve_class(VM_Global_State::loader_env, c_idx);
        if (outer_clss) 
        {
            String* name = clazz->get_constant_pool().get_name_and_type_name(method_idx);
            String* desc = clazz->get_constant_pool().get_name_and_type_descriptor(method_idx);

            TRACE("Looking for enclosing method: class="<<outer_clss->get_name()->bytes 
                <<"; name="<<name->bytes<<"; desc="<<desc->bytes);

            Method* enclosing = outer_clss->lookup_method(name, desc);
            if (enclosing) 
            {
                if (enclosing->is_init()) 
                {
                    return reflection_reflect_constructor(jenv, enclosing);
                } 
                else if (!enclosing->is_clinit()) 
                {
                    return reflection_reflect_method(jenv, enclosing);
                }
            } else {
                //FIXME: check RI compatibility, provide detailed message
                ThrowNew_Quick(jenv, "java/lang/NoSuchMethodException", 
                    "Invalid enclosing method declared");
            }
        } else if (!exn_raised()) {
            exn_raise_object(clazz->get_constant_pool().get_error_cause(c_idx));
        }
    } 
    return NULL;
}
jthrowable create_exception(Class* exc_class, Method* exc_init, jvalue* args) {
    ASSERT_RAISE_AREA;
    assert(hythread_is_suspend_enabled());

    bool suspended_enabled = hythread_is_suspend_enabled();

    if (suspended_enabled) {
        tmn_suspend_disable();
    }

    ManagedObject *man_obj = class_alloc_new_object(exc_class);

    if (!man_obj) {
        exn_raise_object(VM_Global_State::loader_env->java_lang_OutOfMemoryError);
        if (suspended_enabled) {
            tmn_suspend_enable();
        }
        return NULL;
    }

    jthrowable exc_object = oh_allocate_local_handle();
    exc_object->object = man_obj;
    args[0].l = exc_object;

    if (exn_raised()) { //if RuntimeException or Error
        if (suspended_enabled) {
            tmn_suspend_enable();
        }
        return NULL;
    }

    vm_execute_java_method_array((jmethodID) exc_init, 0, args);

    if (suspended_enabled) {
        tmn_suspend_enable();
    }

    return exc_object;
}
Exemplo n.º 16
0
// Create an exception from a given type and a message.
// Set cause to the current thread exception.
static void compile_raise_exception(const char* name, const char* message, Method* method)
{
    assert(hythread_is_suspend_enabled());
    jthrowable old_exc = exn_get();
    exn_clear();

    const char* c = method->get_class()->get_name()->bytes;
    const char* m = method->get_name()->bytes;
    const char* d = method->get_descriptor()->bytes;
    size_t sz = 3 + // a space, a dot, and a terminator
        strlen(message) +
        method->get_class()->get_name()->len +
        method->get_name()->len +
        method->get_descriptor()->len;
    char* msg_raw = (char*)STD_MALLOC(sz);
    assert(msg_raw);
    sprintf(msg_raw, "%s%s.%s%s", message, c, m, d);
    assert(strlen(msg_raw) < sz);

    jthrowable new_exc = exn_create(name, msg_raw, old_exc);
    exn_raise_object(new_exc);
    STD_FREE(msg_raw);
}
Exemplo n.º 17
0
static bool method_can_link_virtual(Class* clss, unsigned cp_index, Method* method, bool _throw)
{
    ASSERT_RAISE_AREA;

    if(method->is_static()) {
        if(_throw) {
            exn_raise_by_name("java/lang/IncompatibleClassChangeError",
                method->get_class()->get_name()->bytes);
        }
        return false;
    }
    if(method->get_class()->is_interface()) {
        if(_throw) {
            char* buf = (char*)STD_ALLOCA(clss->get_name()->len
                + method->get_name()->len + method->get_descriptor()->len + 2);
            sprintf(buf, "%s.%s%s", clss->get_name()->bytes,
                method->get_name()->bytes, method->get_descriptor()->bytes);
            jthrowable exc_object = exn_create("java/lang/AbstractMethodError", buf);
            exn_raise_object(exc_object);
        }
        return false;
    }
    return true;
}