Ejemplo n.º 1
0
// exception catch support for JVMTI, also restore stack after Stack Overflow Error
void jvmti_exception_catch_callback() {
    Registers regs = {0};
    VM_thread *thread = p_TLS_vmthread;
    assert(thread);

    if (thread->regs) {
        regs = *(Registers*)thread->regs;
    }

    M2nFrame* m2n = (M2nFrame *) STD_ALLOCA(m2n_get_size());
    m2n_push_suspended_frame(thread, m2n, &regs);
    M2nFrame* prev_m2n = m2n_get_previous_frame(m2n);

    StackIterator* si = (StackIterator*) STD_ALLOCA(si_size());
    si_fill_from_registers(si, &regs, false, prev_m2n);

    // si_create_from_registers uses large stack space,
    // so guard page restored after its invoke, 
    // but befor ti agent callback invokation, 
    // because it should work on protected page.
    if (p_TLS_vmthread->restore_guard_page) {
        int res = port_thread_restore_guard_page();

        if (res != 0) {
            Global_Env *env = VM_Global_State::loader_env;

            if (si_is_native(si)) {
                m2n_set_last_frame(prev_m2n);

                if ((interpreter_enabled() || (!prev_m2n) ||
                        (m2n_get_frame_type(prev_m2n) & FRAME_NON_UNWINDABLE))) {
                    exn_raise_by_class(env->java_lang_StackOverflowError_Class);
                } else {
                    //si_free(si);
                    exn_throw_by_class(env->java_lang_StackOverflowError_Class);
                }
            } else {
                //si_free(si);
                exn_throw_by_class(env->java_lang_StackOverflowError_Class);
            }
        }

        p_TLS_vmthread->restore_guard_page = false;
    }

    if (!si_is_native(si))
    {
        CodeChunkInfo* catch_cci = si_get_code_chunk_info(si);
        assert(catch_cci);
        Method* catch_method = catch_cci->get_method();
        NativeCodePtr catch_method_location = si_get_ip(si);
        JIT* catch_method_jit = catch_cci->get_jit();
        ManagedObject** exn_obj = (ManagedObject**) si_get_return_pointer(si);
        *exn_obj = jvmti_jit_exception_catch_event_callback_call( *exn_obj,
                catch_method_jit, catch_method, catch_method_location);
    }

    si_transfer_control(si);
}
Ejemplo n.º 2
0
// Interpter of VM
Value Simulator::interpreter(AbstractComponent *_component, Thread *_thread, Value *__args, ArgNo __n)
{
    // Create simulation context
    Simulator sim;
    sim.m_thread = _thread;
    sim.m_component = _component;
    sim.m_domain = _thread->get_current_domain();
    sim.m_function = _thread->get_this_function();
    sim.m_program = sim.m_function->get_program();
    sim.m_argn = __n;
    sim.m_args = __args;
    sim.m_localn = sim.m_function->get_max_local_no();
    sim.m_locals = (Value *)STD_ALLOCA(sizeof(Value) * sim.m_localn);
    sim.m_constantn = sim.m_program->get_constants_count();
    sim.m_constants = sim.m_program->get_constant(0);
    sim.m_object_varn = sim.m_component->m_program->get_object_vars_count();
    sim.m_object_vars = sim.m_component->m_object_vars;
    memset(sim.m_locals, 0, sizeof(Value) * sim.m_localn);

    // Set byte codes
    sim.m_byte_codes = sim.m_function->get_byte_codes_addr();

    // Start simulation
    return sim.run();
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
// exception catch callback to restore stack after Stack Overflow Error
void exception_catch_callback() {
    Registers regs = {0};
    VM_thread *thread = p_TLS_vmthread;
    assert(thread);

    if (thread->regs) {
        regs = *(Registers*)thread->regs;
    }

    M2nFrame* m2n = (M2nFrame *) STD_ALLOCA(m2n_get_size());
    m2n_push_suspended_frame(thread, m2n, &regs);
    M2nFrame* prev_m2n = m2n_get_previous_frame(m2n);

    StackIterator* si = (StackIterator*) STD_ALLOCA(si_size());
    si_fill_from_registers(si, &regs, false, prev_m2n);

    // si_create_from_registers uses large stack space,
    // so guard page restored after its invoke.
    if (p_TLS_vmthread->restore_guard_page) {
        int res = port_thread_restore_guard_page();

        if (res != 0) {
            Global_Env *env = VM_Global_State::loader_env;

            if (si_is_native(si)) {
                m2n_set_last_frame(prev_m2n);

                if ((interpreter_enabled() || (!prev_m2n) ||
                        (m2n_get_frame_type(prev_m2n) & FRAME_NON_UNWINDABLE))) {
                    exn_raise_by_class(env->java_lang_StackOverflowError_Class);
                } else {
                    //si_free(si);
                    exn_throw_by_class(env->java_lang_StackOverflowError_Class);
                }
            } else {
                //si_free(si);
                exn_throw_by_class(env->java_lang_StackOverflowError_Class);
            }
        }

        p_TLS_vmthread->restore_guard_page = false;
    }

    si_transfer_control(si);
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
0
static IDATA rt_jthread_monitor_enter(ManagedObject*  monitor) {
    const unsigned handles_size = (unsigned)(sizeof(ObjectHandlesNew)+sizeof(ManagedObject*)*4);
    ObjectHandlesNew* handels = (ObjectHandlesNew *)STD_ALLOCA(handles_size);
    handels->capacity = 4;
    handels->size = 0;
    handels->next = NULL;

    m2n_set_local_handles(m2n_get_last_frame(), (ObjectHandles *) handels);

    ObjectHandle monitorJavaObj = oh_allocate_local_handle();
    monitorJavaObj->object = monitor;

    IDATA result = jthread_monitor_enter(monitorJavaObj);

    free_local_object_handles2(m2n_get_local_handles(m2n_get_last_frame()));
    m2n_set_local_handles(m2n_get_last_frame(), NULL);

    return result;
}
Ejemplo n.º 7
0
void Simulator::xCHKPARAM()
{
    // Check the count & type of all arguments
    // Pad default if necessary
    if (m_argn < m_function->get_min_arg_no())
        throw_error("Two few arguments to %s, expected %d, got %d.\n",
                    m_function->get_name()->c_str(),
                    m_function->get_min_arg_no(), m_argn);

    if (m_argn > m_function->get_min_arg_no() &&
        !m_function->get_attrib() & Function::RANDOM_ARG)
        throw_error("Two many arguments to %s, expected %d, got %d.\n",
                    m_function->get_name()->c_str(),
                    m_function->get_max_arg_no(), m_argn);

    // Check types
    auto& parameters = (Parameters&)m_function->get_parameters();
    Value *p = m_args;
    for (auto& it : parameters)
    {
        if (it->get_type() != p->m_type &&
            (!it->is_nullable() || p->m_type != NIL))
            // Type is not matched
            throw_error("Bad type of arguments %s, expected %s, got %s.\n",
                        it->get_name()->c_str(),
                        it->get_type(), p->m_type);
    }
    // Append the default parameters if necessary
    if (m_argn < m_function->get_min_arg_no())
    {
        auto *new_args = (Value *)STD_ALLOCA(sizeof(Value) * m_function->get_max_arg_no());
        memcpy(new_args, m_args, sizeof(Value) * m_argn);
        while (m_argn < m_function->get_min_arg_no())
        {
            new_args[m_argn] = parameters[m_argn]->get_default();
            m_argn++;
        }
    }
}
Ejemplo n.º 8
0
static PORT_CDECL int thread_start_func(void* arg)
{
    int err, result;
    port_tls_data_t* tlsdata = NULL;
    thread_start_struct_t* ptr = (thread_start_struct_t*)arg;
    port_threadfunc_t fun = ptr->fun;
    size_t stack_size = ptr->stack_size;
    arg = ptr->arg;
    STD_FREE(ptr);

    if (port_shared_data)
    {
        tlsdata = (port_tls_data_t*)STD_ALLOCA(sizeof(port_tls_data_t));
        err = port_thread_attach_local(tlsdata, FALSE, FALSE, stack_size);
        assert(err == 0);
    }

    result = fun(arg);

    if (tlsdata)
        port_thread_detach();

    return result;
}
Ejemplo n.º 9
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;
}
Ejemplo n.º 10
0
void
JIT_execute_method_default(JIT_Handle jit, jmethodID methodID, jvalue *return_value, jvalue *args) {

    // Detecting errors with object headears on stack when using destructive
    // unwinding.
    void *lastFrame = p_TLS_vmthread->lastFrame;
    p_TLS_vmthread->lastFrame = (void*)&lastFrame;
    //printf("execute: push: prev = 0x%p, curr=0x%p\n", lastFrame, &lastFrame);

//    fprintf(stderr, "Not implemented\n");

    Method *method = (Method*) methodID;
    TRACE("enter method "
          << method->get_class()->get_name()->bytes << " "
          << method->get_name()->bytes << " "
          << method->get_descriptor()->bytes);
    int sz = method->get_num_arg_slots();
    void *meth_addr = method->get_code_addr();
    U_32 *arg_words = (U_32*) STD_ALLOCA(sz * sizeof(U_32));

    int argId = sz;
    int pos = 0;

    assert(!hythread_is_suspend_enabled());
    if (!method->is_static()) {
        ObjectHandle handle = (ObjectHandle) args[pos++].l;
        assert(handle);
        arg_words[--argId] = (unsigned) handle->object;
    }

    const char *mtype = method->get_descriptor()->bytes + 1;
    assert(mtype != 0);

    for(; *mtype != ')'; mtype++) {
        switch(*mtype) {
        case JAVA_TYPE_CLASS:
        case JAVA_TYPE_ARRAY:
        {
            ObjectHandle handle = (ObjectHandle) args[pos++].l;
            arg_words[--argId] = (unsigned) (handle ? handle->object : 0);

            while(*mtype == '[') mtype++;
            if (*mtype == 'L')
                while(*mtype != ';') mtype++;
        }
        break;

        case JAVA_TYPE_SHORT:
            // sign extend
            arg_words[--argId] = (U_32)(I_32) args[pos++].s;
            break;
        case JAVA_TYPE_BYTE:
            // sign extend
            arg_words[--argId] = (U_32)(I_32) args[pos++].b;
            break;
        case JAVA_TYPE_INT:
            // sign extend
            arg_words[--argId] = (U_32)(I_32) args[pos++].i;
            break;

        case JAVA_TYPE_FLOAT:
            arg_words[--argId] = (I_32) args[pos++].i;
            break;
        case JAVA_TYPE_BOOLEAN:
            arg_words[--argId] = (I_32) args[pos++].z;
            break;
        case JAVA_TYPE_CHAR:
            // zero extend
            arg_words[--argId] = (I_32) args[pos++].c;
            break;

        case JAVA_TYPE_LONG:
        case JAVA_TYPE_DOUBLE:
            *(jlong*)&arg_words[argId-2] = args[pos++].j;
            argId -= 2;
            break;
        default:
            LDIE(53, "Unexpected java type");
        }
    }
    assert(argId >= 0);

    jvalue *resultPtr = (jvalue*) return_value;
    Java_Type ret_type = method->get_return_java_type();

    arg_words += argId;
    argId = sz - argId;

    static const IntFuncPtr invoke_managed_func = gen_invoke_int_managed_func();
    static const FloatFuncPtr invoke_float_managed_func = gen_invoke_float_managed_func();
    static const DoubleFuncPtr invoke_double_managed_func = gen_invoke_double_managed_func();

    switch(ret_type) {
    case JAVA_TYPE_VOID:
        invoke_managed_func(arg_words, argId, meth_addr);
        break;
    case JAVA_TYPE_CLASS:
    case JAVA_TYPE_ARRAY:
    case JAVA_TYPE_STRING:
    {
        ManagedObject *ref = ((RefFuncPtr)invoke_managed_func)(arg_words, argId, meth_addr);
        ObjectHandle h = oh_allocate_local_handle();

        if (ref != NULL) {
            h->object = ref;
            resultPtr->l = h;
        } else {
            resultPtr->l = NULL;
        }
    }
    break;

    case JAVA_TYPE_BOOLEAN:
    case JAVA_TYPE_BYTE:
    case JAVA_TYPE_CHAR:
    case JAVA_TYPE_SHORT:
    case JAVA_TYPE_INT:
        resultPtr->i = invoke_managed_func(arg_words, argId, meth_addr);
        break;

    case JAVA_TYPE_FLOAT:
        resultPtr->f = invoke_float_managed_func(arg_words, argId, meth_addr);
        break;

    case JAVA_TYPE_LONG:
        resultPtr->j = ((LongFuncPtr)invoke_managed_func)(arg_words, argId, meth_addr);
        break;

    case JAVA_TYPE_DOUBLE:
        resultPtr->d = invoke_double_managed_func(arg_words, argId, meth_addr);
        break;

    default:
        LDIE(53, "Unexpected java type");
    }

    if (exn_raised()) {
        TRACE("Exception occured: " << exn_get_name());
        if ((resultPtr != NULL) && (ret_type != JAVA_TYPE_VOID)) {
            resultPtr->l = 0; //clear result
        }
    }

    TRACE("exit method "
          << method->get_class()->get_name()->bytes << " "
          << method->get_name()->bytes << " "
          << method->get_descriptor()->bytes);

    // Detecting errors with object headears on stack when using destructive
    // unwinding.
    //printf("execute:  pop: prev = 0x%p, curr=0x%p\n", &lastFrame, lastFrame);
    p_TLS_vmthread->lastFrame = lastFrame;
}
Ejemplo n.º 11
0
// function can be safe point & should be called with disable reqursion = 1
void exn_athrow_regs(Registers * regs, Class_Handle exn_class, bool java_code, bool transfer_control)
{
    assert(!hythread_is_suspend_enabled());
    assert(exn_class);

#ifndef _IPF_
    M2nFrame *cur_m2nf = (M2nFrame *) STD_ALLOCA(m2n_get_size());
    M2nFrame *unw_m2nf;
    ManagedObject *exn_obj = NULL;
    StackIterator *si;
    DebugUtilsTI* ti = VM_Global_State::loader_env->TI;
    VM_thread* vmthread = p_TLS_vmthread;

    if (java_code)
        m2n_push_suspended_frame(vmthread, cur_m2nf, regs);
    else
        // Gregory -
        // Initialize cur_m2nf pointer in case we've crashed in native code that is unwindable,
	// e.g. in the code that sets non-unwindable state for the native code area
        cur_m2nf = m2n_get_last_frame();

    BEGIN_RAISE_AREA;

    si = (StackIterator*) STD_ALLOCA(si_size());
    si_fill_from_native(si);
    ManagedObject *local_exn_obj = NULL;
    exn_obj = exn_propagate_exception(si, &local_exn_obj, exn_class, NULL, NULL, NULL);

    //free local handles
    ObjectHandles* last_m2n_frame_handles = m2n_get_local_handles(cur_m2nf);

    if (last_m2n_frame_handles) {
        free_local_object_handles2(last_m2n_frame_handles);
    }

    if (ti->get_global_capability(DebugUtilsTI::TI_GC_ENABLE_EXCEPTION_EVENT)) {
        VM_thread *thread = p_TLS_vmthread;
        NativeCodePtr callback = (NativeCodePtr)
                jvmti_exception_catch_callback;

        si_copy_to_registers(si, regs);
        vm_set_exception_registers(thread, *regs);
        si_set_callback(si, &callback);
    } else if (p_TLS_vmthread->restore_guard_page) {
        VM_thread *thread = p_TLS_vmthread;
        NativeCodePtr callback = (NativeCodePtr)
                exception_catch_callback;
        si_copy_to_registers(si, regs);
        vm_set_exception_registers(thread, *regs);
        si_set_callback(si, &callback);
    }

    si_copy_to_registers(si, regs);

    if (transfer_control) {
        // Let NCAI to continue single stepping in exception handler
        ncai_setup_signal_step(&vmthread->jvmti_thread, (NativeCodePtr)regs->get_ip());

        set_exception_object_internal(exn_obj);
        si_transfer_control(si);
        assert(!"si_transfer_control should not return");
    } 

    unw_m2nf = si_get_m2n(si);
    //si_free(si);

    END_RAISE_AREA;

    set_exception_object_internal(exn_obj);
    m2n_set_last_frame(unw_m2nf);
#endif
}   //exn_athrow_regs
Ejemplo n.º 12
0
// function can be safe point & should be called with disable reqursion = 1
void exn_throw_for_JIT(ManagedObject* exn_obj, Class_Handle exn_class,
    Method_Handle exn_constr, U_8* jit_exn_constr_args, jvalue* vm_exn_constr_args)
{
/*
 * !!!! NO LOGGER IS ALLOWED IN THIS FUNCTION !!!
 * !!!! RELEASE BUILD WILL BE BROKEN          !!!
 * !!!! NO TRACE2, INFO, WARN, ECHO, ASSERT, ...
 */
    assert(!hythread_is_suspend_enabled());

    if(exn_raised()) {
        return;
    }

    ASSERT_NO_INTERPRETER
    ASSERT_RAISE_AREA;

    if ((exn_obj == NULL) && (exn_class == NULL)) {
        exn_class = VM_Global_State::loader_env->java_lang_NullPointerException_Class;
    }
    ManagedObject* local_exn_obj = exn_obj;
    StackIterator* si = (StackIterator*) STD_ALLOCA(si_size());
    si_fill_from_native(si);

    if (exn_raised()) {
        return;
    }

#ifndef _IPF_
    assert(is_gc_frame_before_m2n_frame());
#endif // _IPF_

    assert(!exn_raised());

    if (si_is_past_end(si)) {
        //FIXME LAZY EXCEPTION (2006.05.12)
        // should be replaced by lazy version
        set_exception_object_internal(local_exn_obj);
        return;
    }

    si_transfer_all_preserved_registers(si);
    assert(!exn_raised());

    DebugUtilsTI* ti = VM_Global_State::loader_env->TI;
    exn_obj = exn_propagate_exception(si, &local_exn_obj, exn_class, exn_constr,
        jit_exn_constr_args, vm_exn_constr_args);

    if (exn_raised()) {
        //si_free(si);
        return;
    }

    M2nFrame* m2nFrame = m2n_get_last_frame();
    ObjectHandles* last_m2n_frame_handles = m2n_get_local_handles(m2nFrame);

    if (last_m2n_frame_handles) {
        free_local_object_handles2(last_m2n_frame_handles);
    }
    set_exception_object_internal(exn_obj);

    if (ti->get_global_capability(DebugUtilsTI::TI_GC_ENABLE_EXCEPTION_EVENT)) {
        Registers regs = {0};
        VM_thread *thread = p_TLS_vmthread;
        NativeCodePtr callback = (NativeCodePtr)
                jvmti_exception_catch_callback;

        si_copy_to_registers(si, &regs);
        vm_set_exception_registers(thread, regs);
        si_set_callback(si, &callback);
    } else if (p_TLS_vmthread->restore_guard_page) {
        Registers regs = {0};
        VM_thread *thread = p_TLS_vmthread;
        NativeCodePtr callback = (NativeCodePtr)
                exception_catch_callback;
        si_copy_to_registers(si, &regs);
        vm_set_exception_registers(thread, regs);
        si_set_callback(si, &callback);
    }

    // don't put any call here
    si_transfer_control(si);
}   //exn_throw_for_JIT
Ejemplo n.º 13
0
// function can be safe point & should be called with disable recursion = 1
static ManagedObject * exn_propagate_exception(
    StackIterator * si,
    ManagedObject ** exn_obj,
    Class_Handle exn_class,
    Method_Handle exn_constr,
    U_8 * jit_exn_constr_args,
    jvalue* vm_exn_constr_args)
{
    assert(!hythread_is_suspend_enabled());
    ASSERT_RAISE_AREA;
    ASSERT_NO_INTERPRETER;

    assert(*exn_obj || exn_class);

    // Save the throw context
    StackIterator *throw_si = (StackIterator*) STD_ALLOCA(si_size());
    memcpy(throw_si, si, si_size());

    // Skip first frame if it is an M2nFrame (which is always a transition from managed to the throw code).
    // The M2nFrame will be removed from the thread's M2nFrame list but transfer control or copy to registers.
    if (si_is_native(si)) {
        si_goto_previous(si);
    }

    Method *interrupted_method;
    NativeCodePtr interrupted_method_location;
    JIT *interrupted_method_jit;
    bool restore_guard_page = p_TLS_vmthread->restore_guard_page;

    if (!si_is_native(si))
    {
        CodeChunkInfo *interrupted_cci = si_get_code_chunk_info(si);
        assert(interrupted_cci);
        interrupted_method = interrupted_cci->get_method();
        interrupted_method_location = si_get_ip(si);
        interrupted_method_jit = interrupted_cci->get_jit();
    }
    else
    {
        interrupted_method = m2n_get_method(si_get_m2n(si));
        interrupted_method_location = 0;
        interrupted_method_jit = 0;
    }

    if (NULL != *exn_obj)
    {
        // Gregory - When *exn_obj is NULL it means we're called from exn_athrow_regs
        // which means that IP points exactly to the right location. But
        // when *exn_obj is not NULL, it means that we're called from exn_throw_for_JIT
        // where *exn_obj is already constructed and is thrown by code via athrow.
        // So in this case IP reported by stack iterator is past the athrow bytecode
        // and should be moved back to be inside of bytecode location for interrupted
        // method.

        interrupted_method_location = (NativeCodePtr)((POINTER_SIZE_INT)interrupted_method_location - 1);

        // Determine the type of the exception for the type tests below.
        exn_class = (*exn_obj)->vt()->clss;
    }

#ifdef VM_STATS
    assert(exn_class);
    exn_class->class_thrown();
    UNSAFE_REGION_START
    VM_Statistics::get_vm_stats().num_exceptions++;
    UNSAFE_REGION_END
#endif // VM_STATS

    // Remove single step breakpoints which could have been set on the
    // exception bytecode
    DebugUtilsTI *ti = VM_Global_State::loader_env->TI;
    if (ti->isEnabled() && ti->is_single_step_enabled())
    {
        jvmti_thread_t jvmti_thread = jthread_self_jvmti();
        ti->vm_brpt->lock();
        if (NULL != jvmti_thread->ss_state)
        {
            jvmti_remove_single_step_breakpoints(ti, jvmti_thread);
        }
        ti->vm_brpt->unlock();
    }

    // When VM is in shutdown stage we need to execute "finally" clause to
    // release monitors and propagate an exception to the upper frames.
    Class_Handle search_exn_class = !VM_Global_State::loader_env->IsVmShutdowning()
        ? exn_class : VM_Global_State::loader_env->JavaLangObject_Class;

    if (!si_is_native(si))
    {
        bool same_frame = true;
        while (!si_is_past_end(si) && !si_is_native(si)) {
            CodeChunkInfo *cci = si_get_code_chunk_info(si);
            assert(cci);
            Method *method = cci->get_method();
            JIT *jit = cci->get_jit();
            assert(method && jit);
            NativeCodePtr ip = si_get_ip(si);
            bool is_ip_past = !!si_get_jit_context(si)->is_ip_past;

#ifdef VM_STATS
            cci->num_throws++;
#endif // VM_STATS

            // Examine this frame's exception handlers looking for a match
            unsigned num_handlers = cci->get_num_target_exception_handlers();
            for (unsigned i = 0; i < num_handlers; i++) {
                Target_Exception_Handler_Ptr handler =
                    cci->get_target_exception_handler_info(i);
                if (!handler)
                    continue;
                if (handler->is_in_range(ip, is_ip_past)
                    && handler->is_assignable(search_exn_class)) {
                    // Found a handler that catches the exception.
#ifdef VM_STATS
                    cci->num_catches++;
                    if (same_frame) {
                        VM_Statistics::get_vm_stats().num_exceptions_caught_same_frame++;
                    }
                    if (handler->is_exc_obj_dead()) {
                        VM_Statistics::get_vm_stats().num_exceptions_dead_object++;
                        if (!*exn_obj) {
                            VM_Statistics::get_vm_stats().num_exceptions_object_not_created++;
                        }
                    }
#endif // VM_STATS

                    if (restore_guard_page) {
                        bool res = check_stack_size_enough_for_exception_catch(si_get_sp(si));
                        //must always be enough. otherwise program behavior is unspecified: finally blocks, monitor exits are not executed
                        assert(res); 
                        if (!res) {
                            break;
                        }

                    }

                    // Setup handler context
                    jit->fix_handler_context(method, si_get_jit_context(si));
                    si_set_ip(si, handler->get_handler_ip(), false);

                    // Start single step in exception handler
                    if (ti->isEnabled() && ti->is_single_step_enabled())
                    {
                        jvmti_thread_t jvmti_thread = jthread_self_jvmti();
                        ti->vm_brpt->lock();
                        if (NULL != jvmti_thread->ss_state)
                        {
                            uint16 bc;
                            NativeCodePtr ip = handler->get_handler_ip();
                            OpenExeJpdaError UNREF result =
                                jit->get_bc_location_for_native(method, ip, &bc);
                            assert(EXE_ERROR_NONE == result);

                            jvmti_StepLocation method_start = {(Method *)method, ip, bc, false};

                            jvmti_set_single_step_breakpoints(ti, jvmti_thread,
                                &method_start, 1);
                        }
                        ti->vm_brpt->unlock();
                    }

                    // Create exception if necessary
                    if (!*exn_obj && !handler->is_exc_obj_dead()) {
                        assert(!exn_raised());

                        *exn_obj = create_lazy_exception(exn_class, exn_constr,
                            jit_exn_constr_args, vm_exn_constr_args);
                    }

                    if (jvmti_is_exception_event_requested()) {
                        // Create exception if necessary
                        if (NULL == *exn_obj) {
                            *exn_obj = create_lazy_exception(exn_class, exn_constr,
                                jit_exn_constr_args, vm_exn_constr_args);
                        }

                        // Reload exception object pointer because it could have
                        // moved while calling JVMTI callback

                        *exn_obj = jvmti_jit_exception_event_callback_call(*exn_obj,
                            interrupted_method_jit, interrupted_method,
                            interrupted_method_location,
                            jit, method, handler->get_handler_ip());
                    }

                    CTRACE(("setting return pointer to %d", exn_obj));

                    si_set_return_pointer(si, (void **) exn_obj);
                    //si_free(throw_si);
                    return NULL;
                }
            }

            // No appropriate handler found, undo synchronization
            vm_monitor_exit_synchronized_method(si);

            jvalue ret_val = {(jlong)0};
            jvmti_process_method_exception_exit_event(
                reinterpret_cast<jmethodID>(method), JNI_TRUE, ret_val, si);

            // Goto previous frame
            si_goto_previous(si);
            same_frame = false;
        }
    }
    // Exception propagates to the native code
    assert(si_is_native(si));

    // The current thread exception is set to the exception and we return 0/NULL to the native code
    if (*exn_obj == NULL) {
        *exn_obj = create_lazy_exception(exn_class, exn_constr,
            jit_exn_constr_args, vm_exn_constr_args);
    }
    assert(!hythread_is_suspend_enabled());

    CodeChunkInfo *catch_cci = si_get_code_chunk_info(si);
    Method *catch_method = NULL;
    if (catch_cci)
        catch_method = catch_cci->get_method();

    // Reload exception object pointer because it could have
    // moved while calling JVMTI callback
    if (exn_raised()) {
        //si_free(throw_si);
        return NULL;
    }

    *exn_obj = jvmti_jit_exception_event_callback_call(*exn_obj,
        interrupted_method_jit, interrupted_method, interrupted_method_location,
        NULL, NULL, NULL);

    //si_free(throw_si);
    return *exn_obj;
}   //exn_propagate_exception
Ejemplo n.º 14
0
/**
 * Dumps graph node in file in DOT format.
 */
void vf_Graph::DumpDotGraph()
{
#if _VF_DEBUG
    /**
     * Graphviz has a hardcoded label length limit. Windows has a file
     * name length limit as well.
     */
    const int MAX_LABEL_LENGTH = 80;

    // get class and method name
    const char *class_name = class_get_name(m_ctx->m_class);

    // create file name
    size_t len = strlen(class_name) + strlen(m_ctx->m_name)
        + strlen(m_ctx->m_descriptor) + 6;
    char *fname = (char *) STD_ALLOCA(len);
    sprintf(fname, "%s_%s%s", class_name, m_ctx->m_name, m_ctx->m_descriptor);

    char *f_start;
    char *pointer;
    if (len > MAX_LABEL_LENGTH) {
        f_start = fname + len - MAX_LABEL_LENGTH;
        // shift to the start of the nearest lexem
        for (pointer = f_start;; pointer++) {
            if (isalnum(*pointer)) {
                continue;
            } else if (!*pointer) {     // end of the string
                break;
            } else {
                // record the first matching position
                f_start = pointer;
                break;
            }
        }
    } else {
        f_start = fname;
    }

    for (pointer = f_start;; pointer++) {
        if (isalnum(*pointer)) {
            continue;
        } else if (!*pointer) { // end of the string
            break;
        } else {
            *pointer = '_';
        }
    }
    // pointer currently points to the end of the string
    sprintf(pointer, ".dot");

    // create .dot file
    ofstream fout(f_start);
    if (fout.fail()) {
        VF_DEBUG("vf_Graph::DumpDotGraph: error opening file: " << f_start);
        return;
    }
    // create name of graph
    sprintf(fname, "%s.%s%s", class_name, m_ctx->m_name, m_ctx->m_descriptor);

    // print graph to file
    DumpDotHeader(f_start, fout);
    ResetNodeIterator();
    while (HasMoreElements()) {
        DumpDotNode(GetNextNode(), fout);
    }
    DumpDotEnd(fout);

    // close file
    fout.flush();
    fout.close();
#endif // _VF_DEBUG
}                               // vf_Graph::DumpDotGraph