Пример #1
0
static void m2n_free_local_handles() {
    assert(!hythread_is_suspend_enabled());

    if (exn_raised()) {
        exn_rethrow();
    }

    M2nFrame * m2n = m2n_get_last_frame();
    free_local_object_handles3(m2n->local_object_handles);
}
Пример #2
0
/*
 * Inflates the compressed lockword into fat fat_monitor
 */
hythread_monitor_t VMCALL hythread_inflate_lock(hythread_thin_monitor_t *lockword_ptr) {
    hythread_monitor_t fat_monitor;
    IDATA status;
    IDATA fat_monitor_id;
    U_32 lockword;
    int i;

    // we don't need to write lock on lock_table during all this function because
    // the only invariant we need is 'fat lock is not in the fat lock table before we put it'

    // however this invariant is true because we hold monitor->mutex during this function
    // so it cannot be called twice for the signle monitor concurrently

    lockword = *lockword_ptr;
    if (IS_FAT_LOCK (lockword)) {
        return locktable_get_fat_monitor(FAT_LOCK_ID(lockword));
    }
#ifdef LOCK_RESERVATION
    // unreserve lock first
    if (IS_RESERVED(lockword)) {
        unreserve_self_lock(lockword_ptr);
        lockword = *lockword_ptr;
    }
    assert(!IS_RESERVED(lockword));
#endif 

    assert(hythread_owns_thin_lock(tm_self_tls, lockword));
    assert(!hythread_is_suspend_enabled());

    CTRACE(("inflation begin for %x thread: %d", lockword, tm_self_tls->thread_id));
    status = hythread_monitor_init(&fat_monitor, 0); // allocate fat fat_monitor    
    //assert(status == TM_ERROR_NONE);  
    if (status != TM_ERROR_NONE) {
        return NULL;
    } 
    status = hythread_monitor_enter(fat_monitor);
    if (status != TM_ERROR_NONE) {
        return NULL;
    } 
    
    for (i = RECURSION(lockword); i > 0; i--) {
        CTRACE(("inflate recursion monitor"));
        status = hythread_monitor_enter(fat_monitor);  // transfer recursion count to fat fat_monitor   
        assert(status == TM_ERROR_NONE);     
    }     
    fat_monitor_id = locktable_put_fat_monitor(fat_monitor); // put fat_monitor into lock table
    set_fat_lock_id(lockword_ptr, fat_monitor_id);
    CTRACE(("hythread_inflate_lock  %d thread: %d\n", FAT_LOCK_ID(*lockword_ptr), tm_self_tls->thread_id));
    //assert(FAT_LOCK_ID(*lockword_ptr) != 2);
    CTRACE(("FAT ID : 0x%x", *lockword_ptr));
#ifdef LOCK_RESERVATION
    assert(!IS_RESERVED(*lockword_ptr));
#endif
    return fat_monitor;
}
void exn_throw_by_name_internal(const char* exc_name, const char* exc_message,
    jthrowable exc_cause)
{
    BEGIN_RAISE_AREA;
    // functions can be invoked in suspend disabled and enabled state
    if (!hythread_is_suspend_enabled()) {
        // exception is throwing, so suspend can be enabled safely
        tmn_suspend_enable();
    }
    assert(hythread_is_suspend_enabled());
    Class *exc_class = get_exc_class(exc_name);

    if (exc_class == NULL) {
        assert(exn_raised());
        exn_rethrow();
        return; // unreachable code
    }
    exn_throw_by_class_internal(exc_class, exc_message, exc_cause);
    END_RAISE_AREA;
}
void exn_raise_by_name_internal(const char* exc_name, const char* exc_message,
    jthrowable exc_cause)
{
    assert(hythread_is_suspend_enabled());
    Class *exc_class = get_exc_class(exc_name);

    if (exc_class == NULL) {
        assert(exn_raised());
        return;
    }
    exn_raise_by_class_internal(exc_class, exc_message, exc_cause);
}
Пример #5
0
jthrowable exn_create(const char *exc_name, const char *exc_message, jthrowable cause)
{
    ASSERT_RAISE_AREA;
    assert(hythread_is_suspend_enabled());
    Class *exc_class = get_exc_class(exc_name);

    if (exc_class == NULL) {
        assert(exn_raised());
        return NULL;
    }
    return exn_create(exc_class, exc_message, cause);
}   // exn_create
void exn_throw_by_class_internal(Class* exc_class, const char* exc_message,
    jthrowable exc_cause)
{
    BEGIN_RAISE_AREA;
    // functions can be invoked in suspend disabled and enabled state
    if (!hythread_is_suspend_enabled()) {
        // exception is throwing, so suspend can be enabled safely
        tmn_suspend_enable();
    }
    assert(hythread_is_suspend_enabled());
#ifdef VM_LAZY_EXCEPTION
    //set_unwindable(false);

    jvalue args[3];
    Method* exc_init = prepare_exc_creating(
            exc_class, args, exc_message, exc_cause);

    if (NULL == exc_init) {
        CTRACE(("%s",
            "exn_throw_by_class(),create exception and delegating to exn_throw_for_JIT()"));
        jthrowable exc_object = exn_create(exc_class, exc_message, exc_cause);
        exn_rethrow_if_pending();
        //set_unwindable(true);
        exn_throw_object_internal(exc_object);
    } else {
        CTRACE(("%s", "exn_throw_by_class(), lazy delegating to exn_throw_for_JIT()"));
        //set_unwindable(true);

        // no return, so enable isn't required
        tmn_suspend_disable();
        exn_throw_for_JIT(NULL, exc_class, exc_init, NULL, args);
        //tmn_suspend_enable();
    }
#else
    jthrowable exc_object = exn_create(exc_class, exc_message, exc_cause);
    exn_rethrow_if_pending();
    exn_throw_object_internal(exc_object);
#endif
    END_RAISE_AREA;
}
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;
}
Пример #8
0
Class_Handle class_find_class_from_loader(Class_Loader_Handle loader, const char* n, Boolean init)
{
    ASSERT_RAISE_AREA;
    assert(hythread_is_suspend_enabled()); // -salikh
    char *new_name = strdup(n);
    char *p = new_name;
    while (*p) {
        if (*p == '.') *p = '/';
        p++;
    }
    String* name = VM_Global_State::loader_env->string_pool.lookup(new_name);
    STD_FREE(new_name);
    Class* ch;
    if (loader) {
        ch = class_load_verify_prepare_by_loader_jni(
            VM_Global_State::loader_env, name, loader);
    } else {
        assert(hythread_is_suspend_enabled());
        ch = class_load_verify_prepare_from_jni(VM_Global_State::loader_env, name);
    }
    if (!ch) return NULL;
    // All initialization from jni should not propagate exceptions and
    // should return to calling native method.
    if(init) {
        class_initialize_from_jni(ch);

        if (exn_raised()) {
            return NULL;
        }
    }

    if(exn_raised()) {
        return 0;
    }

    return ch;
}
Пример #9
0
// Return the type of incompatible class change exception
Class_Handle exn_get_incompatible_class_change_exception_type()
{
    assert(hythread_is_suspend_enabled());
    Class *exn_clss;

    Global_Env *env = VM_Global_State::loader_env;
    String *exc_str =
        env->string_pool.lookup("java/lang/IncompatibleClassChangeError");
    exn_clss =
        env->bootstrap_class_loader->LoadVerifyAndPrepareClass(env, exc_str);
    assert(exn_clss);


    return exn_clss;
}
//FIXME LAZY EXCEPTION (2006.05.13)
// cause can be null
static Method* prepare_exc_creating(Class* exc_class, jvalue* args) {
    ASSERT_RAISE_AREA;
    assert(hythread_is_suspend_enabled());

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

    // Check that constructor is found
    if (NULL == exc_init) {
        return prepare_exc_creating(exc_class, args, "");
    }

    // Returns found constructor
    return exc_init;
}
jthrowable create_exception(Class* exc_class,
    const char* exc_message, jthrowable exc_cause)
{
    ASSERT_RAISE_AREA;
    assert(hythread_is_suspend_enabled());
    jvalue args[3];
    Method *exc_init =
        prepare_exc_creating(exc_class, args, exc_message, exc_cause);

    if (exc_init == NULL){
        return NULL;
    }

    return create_exception(exc_class, exc_init, args);
} // create_exception(Class *exc_class, const char *exc_message, jthrowable exc_cause)
Пример #12
0
Method *interp_resolve_special_method(Class *clazz, int methodId) {
    assert(!hythread_is_suspend_enabled());
    Compilation_Handle handle;
    handle.env = VM_Global_State::loader_env;
    handle.jit = 0;

    hythread_suspend_enable();
    Method *method = resolve_special_method(
            (Compile_Handle*)&handle, clazz, methodId);
    hythread_suspend_disable();
    if (!method) {
        if (!exn_raised())
            class_throw_linking_error_for_interpreter(clazz, methodId, OPCODE_INVOKESPECIAL);
    }
    return method;
}
Пример #13
0
Class* interp_resolve_class_new(Class *clazz, int classId) {
    assert(!hythread_is_suspend_enabled());
    Compilation_Handle handle;
    handle.env = VM_Global_State::loader_env;
    handle.jit = 0;

    hythread_suspend_enable();
    Class *objClass = resolve_class_new((Compile_Handle*)&handle, clazz, classId); 
    hythread_suspend_disable();
    if (!objClass) {
        if (!exn_raised())
            class_throw_linking_error_for_interpreter(clazz, classId, OPCODE_NEW);
    }

    return objClass;
}
Пример #14
0
jthrowable exn_create(Class* exc_class, const char* exc_message, jthrowable exc_cause)
{
    ASSERT_RAISE_AREA;
    assert(hythread_is_suspend_enabled());
    jthrowable exc_object = create_exception(exc_class, exc_message, exc_cause);

    if (exc_object == NULL) {
        exc_object = create_exception(exc_class, exc_message , NULL);

        if (exc_object == NULL) {
            return NULL;
        }
        init_cause(exc_object, exc_cause);
    }
    return exc_object;
}
Пример #15
0
// Return the type of negative array size exception
Class_Handle exn_get_negative_array_size_exception_type()
{
    assert(hythread_is_suspend_enabled());
    Class *exn_clss;


    Global_Env *env = VM_Global_State::loader_env;
    String *exc_str =
        env->string_pool.lookup("java/lang/NegativeArraySizeException");
    exn_clss =
        env->bootstrap_class_loader->LoadVerifyAndPrepareClass(env, exc_str);
    assert(exn_clss);


    return exn_clss;
}
Пример #16
0
static void class_report_failure(Class* target, uint16 cp_index, jthrowable exn)
{
    ConstantPool& cp = target->get_constant_pool();
    assert(cp.is_valid_index(cp_index));
    assert(hythread_is_suspend_enabled());
    assert(exn);

    tmn_suspend_disable();
    target->lock();
    if (!cp.is_entry_in_error(cp_index)) {
        // vvv - This should be atomic change
        cp.resolve_as_error(cp_index, exn);
        // ^^^
    }
    target->unlock();
    tmn_suspend_enable();
}
Пример #17
0
Field* interp_resolve_static_field(Class *clazz, int fieldId, bool putfield) {
    assert(!hythread_is_suspend_enabled());
    Compilation_Handle handle;
    handle.env = VM_Global_State::loader_env;
    handle.jit = 0;

    hythread_suspend_enable();
    Field *field =
        resolve_static_field((Compile_Handle*)&handle, clazz, fieldId, putfield);
    hythread_suspend_disable();
    if (!field) {
        if (!exn_raised())
            class_throw_linking_error_for_interpreter(clazz, fieldId,
                    putfield?OPCODE_PUTSTATIC:OPCODE_GETSTATIC);
    }
    return field;
}
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;
}
// function is safe point & should be called in disable mode in safe enviroment
ManagedObject* __stdcall get_exception_object_internal()
{
    assert(!hythread_is_suspend_enabled());
    if (NULL != p_TLS_vmthread->thread_exception.exc_object) {
        return p_TLS_vmthread->thread_exception.exc_object;
    } else if (NULL != p_TLS_vmthread->thread_exception.exc_class) {
        Exception* exception = (Exception*)&(p_TLS_vmthread->thread_exception);

        // suspend can be enabeled in safe enviroment
        tmn_suspend_enable();
        jthrowable exc_object = create_exception(exception);
        tmn_suspend_disable();

        return exc_object->object;
    } else {
        return NULL;
    }
} // get_exc_object_internal
void init_cause(jthrowable exc_object, jthrowable exc_cause) {
    ASSERT_RAISE_AREA;
    assert(exc_cause);
    assert(hythread_is_suspend_enabled());

    tmn_suspend_disable();

    Class* exc_class = exc_object->object->vt()->clss;
    Method *init_cause_method = class_lookup_method_recursive(exc_class,
        "initCause", "(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
    assert(init_cause_method);
    jvalue args[2];
    args[0].l = exc_object;
    args[1].l = exc_cause;
    jvalue ret_val;
    vm_execute_java_method_array((jmethodID) init_cause_method, &ret_val,
        args);
    tmn_suspend_enable();
}
Пример #21
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
Пример #22
0
static JIT_Result compile_do_compilation(Method* method)
{
    ASSERT_RAISE_AREA;
    assert(hythread_is_suspend_enabled());
    tmn_suspend_disable();
    class_initialize(method->get_class());
    tmn_suspend_enable();
   
    method->lock();
    if (exn_raised()) {
        method->unlock();
        return JIT_FAILURE;
    } else if (method->get_state() == Method::ST_Compiled) {
        method->unlock();
        return JIT_SUCCESS;
    } else if (method->get_state()==Method::ST_NotCompiled && exn_raised()) {
        method->unlock();
        return JIT_FAILURE;
    } else if(!check_available_stack_size(0x8000)) {
        method->unlock();
        return JIT_FAILURE;
    }

    if (method->is_native()) {
        JIT_Result res = compile_prepare_native_method(method);            
        if (res == JIT_SUCCESS) {
            compile_flush_generated_code();
            method->set_state(Method::ST_Compiled);
            method->do_jit_recompiled_method_callbacks();
            method->apply_vtable_patches();
        } else {
            method->set_state(Method::ST_NotCompiled);
            compile_raise_exception("java/lang/UnsatisfiedLinkError", "Cannot load native ", method);
        }
        method->unlock();
        return res;
    } else {
        // Call an execution manager to compile the method.
        // An execution manager is safe to call from multiple threads.
        method->unlock();
        return VM_Global_State::loader_env->em_interface->CompileMethod(method);
    }
}
Пример #23
0
/**
 * Runs java.lang.Thread.detach() method.
 */
static jint run_java_detach(jthread java_thread)
{
    assert(hythread_is_suspend_enabled());

    JNIEnv *jni_env = jthread_get_JNI_env(java_thread);
    Global_Env *vm_env = jni_get_vm_env(jni_env);
    Class *thread_class = vm_env->java_lang_Thread_Class;

    static Method *detach = NULL;
    if (detach == NULL) {
        const char *method_name = "detach";
        const char *descriptor = "(Ljava/lang/Throwable;)V";
        detach = class_lookup_method(thread_class, method_name, descriptor);
        if (detach == NULL) {
            TRACE("Failed to find thread's detach method " << descriptor <<
                  " , exception = " << exn_get());
            return TM_ERROR_INTERNAL;
        }
    }

    // Initialize arguments.
    jvalue args[2];
    args[0].l = java_thread;
    if (vm_env->IsVmShutdowning()) {
        args[1].l = NULL;
    } else {
        args[1].l = exn_get();
    }
    exn_clear();

    hythread_suspend_disable();
    vm_execute_java_method_array((jmethodID) detach, 0, args);
    hythread_suspend_enable();

    if (exn_raised()) {
        TRACE
            ("java.lang.Thread.detach(Throwable) method completed with an exception: "
             << exn_get_name());
        return TM_ERROR_INTERNAL;
    }
    return TM_ERROR_NONE;
}
Пример #24
0
ManagedObject* Class::allocate_instance()
{
    assert(!hythread_is_suspend_enabled());
    //assert(is_initialized());
    ManagedObject* new_instance =
        (ManagedObject*)vm_alloc_and_report_ti(m_instance_data_size,
            m_allocation_handle, vm_get_gc_thread_local(), this);
    if(new_instance == NULL)
    {
        return NULL;
    }

#ifdef VM_STATS
    UNSAFE_REGION_START
    VM_Statistics::get_vm_stats().num_class_alloc_new_object++;
    instance_allocated(m_instance_data_size);
    UNSAFE_REGION_END
#endif //VM_STATS

    return new_instance;
}
Пример #25
0
jvmtiError
interpreter_ti_getObject(
        jvmtiEnv* env,
        VM_thread *thread,
        jint depth,
        jint slot,
        jobject* value_ptr)
{
    StackFrame *frame;

    // check error condition: JVMTI_ERROR_NULL_POINTER
    if( value_ptr == NULL )
        return JVMTI_ERROR_NULL_POINTER;

    // check error condition: JVMTI_ERROR_NO_MORE_FRAMES
    // check error condition: JVMTI_ERROR_OPAQUE_FRAME
    // check error condition: JVMTI_ERROR_INVALID_SLOT
    jvmtiError err = interpreter_ti_getLocalCommon(env, thread, depth, slot, &frame);
    if (err != JVMTI_ERROR_NONE)
        return err;

    // TODO: check error condition: JVMTI_ERROR_TYPE_MISMATCH
    // partial check error condition: JVMTI_ERROR_TYPE_MISMATCH
    if (frame->locals.ref(slot) == 0) {
        return JVMTI_ERROR_TYPE_MISMATCH;
    }

    assert(hythread_is_suspend_enabled());
    hythread_suspend_disable();
    ManagedObject *obj = UNCOMPRESS_INTERP(frame->locals(slot).ref);
    if (NULL == obj) {
        *value_ptr = NULL;
    } else {
        ObjectHandle handle = oh_allocate_local_handle();
        handle->object = obj;
        *value_ptr = (jobject) handle;
    }
    hythread_suspend_enable();
    return JVMTI_ERROR_NONE;
}
Class *get_exc_class(const char *exception_name)
{
    ASSERT_RAISE_AREA;
    assert(hythread_is_suspend_enabled());
    Global_Env *env = VM_Global_State::loader_env;
    String *exc_str = env->string_pool.lookup(exception_name);
    Class *exc_class =
        env->bootstrap_class_loader->LoadVerifyAndPrepareClass(env, exc_str);

    if (exc_class == NULL) {
        return NULL;
    }

    tmn_suspend_disable();
    class_initialize(exc_class);
    tmn_suspend_enable();

    if (exn_raised()) {
        return NULL;
    }

    return exc_class;
}
Пример #27
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);
}
Пример #28
0
/**
 * Detaches current thread from VM.
 */
jint vm_detach(jobject java_thread)
{
    assert(hythread_is_suspend_enabled());

    hythread_t native_thread = jthread_get_native_thread(java_thread);
    assert(native_thread);
    vm_thread_t p_vm_thread = jthread_get_vm_thread(native_thread);
    assert(p_vm_thread);

    // Send Thread End event
    if(jvmti_should_report_event(JVMTI_EVENT_THREAD_END)) {
        jvmti_send_thread_start_end_event(p_vm_thread, 0);
    }

    // change java_status for native thread
    native_thread->java_status = TM_STATUS_ALLOCATED;

    if (native_thread == hythread_self()) {
        // Notify GC about thread detaching.
        // FIXME - GC notify detach thread works for current thread only
        gc_thread_kill(&p_vm_thread->_gc_private_information);
    }

    if (ti_is_enabled())
    {
        apr_status_t UNREF status;
        status = port_vmem_free(
            p_vm_thread->jvmti_thread.jvmti_jit_breakpoints_handling_buffer,
            TM_JVMTI_MAX_BUFFER_SIZE);
        assert(status == APR_SUCCESS);
    }

    // Destroy current VM_thread pool and zero VM_thread structure
    jthread_deallocate_vm_thread_pool(p_vm_thread);

    return JNI_OK;
}
Пример #29
0
static Class_Handle method_get_return_type_class(Method_Handle m)
{
    assert(hythread_is_suspend_enabled());
    Method *method = (Method *)m;
    Global_Env *env = VM_Global_State::loader_env;
    Java_Type UNUSED t = method->get_return_java_type();
    assert(t == JAVA_TYPE_CLASS || t == JAVA_TYPE_ARRAY);
    const char *descr = method->get_descriptor()->bytes;
    while(*descr != ')')
        descr++;
    descr++;
    String *n;
    if(descr[0] == 'L') {
        descr++;
        size_t len = strlen(descr);
        n = env->string_pool.lookup(descr, len-1);
    } else {
        n = env->string_pool.lookup(descr);
    }

    Class *clss = method->get_class();
    Class *c = clss->get_class_loader()->LoadVerifyAndPrepareClass(env, n);
    return c;
} //method_get_return_type_class
static Method* prepare_exc_creating(Class* exc_class, jvalue* args,
    jthrowable exc_cause) {
    ASSERT_RAISE_AREA;
    assert(hythread_is_suspend_enabled());

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

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

    // Check that constructor is found
    if (exc_init == NULL){
        return prepare_exc_creating(exc_class, args, "", exc_cause);
    }

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

    // Returns found constructor
    return exc_init;
}