Esempio n. 1
0
NativeCodePtr compile_me(Method* method)
{
    ASSERT_RAISE_AREA;
    ASSERT_NO_INTERPRETER;
    TRACE("compile_me " << method);

    GcFrame gc;
    compile_protect_arguments(method, &gc);

    if (exn_raised()) {
        return NULL;
     }

    tmn_suspend_enable();
    if (method->is_abstract()) { 
        compile_raise_exception("java/lang/AbstractMethodError", "", method); 
        tmn_suspend_disable(); 
        return NULL; 
    }

    DebugUtilsTI *ti = VM_Global_State::loader_env->TI;
    JIT_Result res = compile_do_compilation(method);

    if (res != JIT_SUCCESS) {
        INFO2("compile", "Cannot compile " << method);
        if (!exn_raised()) {
            compile_raise_exception("java/lang/InternalError", "Cannot compile ", method);
        }
        tmn_suspend_disable();
        return NULL;
    }
    tmn_suspend_disable();

    NativeCodePtr entry_point = method->get_code_addr();
    INFO2("compile.code", "Compiled method " << method
            << ", entry " << entry_point);

    if (method->get_pending_breakpoints() != 0)
        jvmti_set_pending_breakpoints(method);
    if(ti->isEnabled() && ti->is_single_step_enabled()
        && !method->is_native())
    {
        jvmti_thread_t jvmti_thread = jthread_self_jvmti();
        assert(jvmti_thread);
        jvmti_set_single_step_breakpoints_for_method(ti, jvmti_thread, method);
    }

    return entry_point;
} // compile_me
void exn_raise_by_class_internal(Class* exc_class, const char* exc_message,
    jthrowable exc_cause)
{
#ifdef VM_LAZY_EXCEPTION
    CTRACE(("%s", "exn_raise_object(), propagating lazy & non-destructively"));

    tmn_suspend_disable_recursive();
    p_TLS_vmthread->thread_exception.exc_class = exc_class;
    p_TLS_vmthread->thread_exception.exc_message = exc_message;

    if (exc_cause != NULL) {
        p_TLS_vmthread->thread_exception.exc_cause = exc_cause->object;
    } else {
        p_TLS_vmthread->thread_exception.exc_cause = NULL;
    }
    tmn_suspend_enable_recursive();
#else
    assert(hythread_is_suspend_enabled());
    jthrowable exc_object = exn_create(exc_class, exc_message, exc_cause);

    if (exn_raised()){
        return;
    }
    exn_raise_object_internal(exc_object);
#endif
}
Esempio n. 3
0
//
// Given a class handle cl construct a class handle of the type
// representing array of cl.
//
Class_Handle class_get_array_of_class(Class_Handle cl)
{
    Global_Env *env = VM_Global_State::loader_env;
    Class *arr_clss = resolve_class_array_of_class(env, cl);
    assert(arr_clss || exn_raised());

    return arr_clss;
} // class_get_array_of_class
Esempio n. 4
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);
    }
}
Esempio n. 5
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);
}
/*
 * Raw Monitor Wait
 *
 * Wait for notification of the raw monitor.
 *
 * REQUIRED Functionality.
 */
jvmtiError JNICALL
jvmtiRawMonitorWait(jvmtiEnv* env,
                    jrawMonitorID monitor,
                    jlong millis)
{
    jvmtiError res = (jvmtiError)jthread_raw_monitor_wait(monitor, millis);
    if (exn_raised() && res == JVMTI_ERROR_INTERRUPT)
        return JVMTI_ERROR_NONE;
    return res;
} // jvmtiRawMonitorWait
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_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);
}
Esempio n. 9
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;
}
Esempio n. 10
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;
}
Esempio n. 11
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;
}
Esempio n. 12
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;
}
Esempio n. 13
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;
}
Esempio n. 14
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;
}
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;
}
Esempio n. 16
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;
}
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;
}
Esempio n. 19
0
JNIEXPORT jclass JNICALL Java_java_lang_VMClassRegistry_loadBootstrapClass
    (JNIEnv *jenv, jclass, jstring name)
{
    // obtain char* for the name
    const char* buf = GetStringUTFChars(jenv, name, NULL);
    // set flag to detect if the requested class is not on the bootclasspath
    p_TLS_vmthread->class_not_found = true;
    Class_Handle clss = class_find_class_from_loader(NULL, buf, FALSE);
    ReleaseStringUTFChars(jenv, name, buf);
    if (clss) {
        // filter out primitive types for compatibility
        return clss->is_primitive() ? NULL : jni_class_from_handle(jenv, clss);
    } else {
        assert(exn_raised());
        if(p_TLS_vmthread->class_not_found) 
        {
            // the requested class is not on the bootclasspath
            // delegation model requires letting child loader(s) to continue 
            // with searching on their paths, so reset the exception
            exn_clear();
        }
        return NULL;
    }
}
Esempio n. 20
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
Esempio n. 21
0
void exn_rethrow_if_pending()
{
    if (exn_raised()) {
        exn_rethrow();
    }
}   //exn_rethrow_if_pending
Esempio n. 22
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
Esempio n. 23
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
Esempio n. 24
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
Esempio n. 25
0
Class* Class::_resolve_class(Global_Env* env,
                             unsigned cp_index)
{
    assert(hythread_is_suspend_enabled());
    ConstantPool& cp = m_const_pool;

    lock();
    if(cp.is_entry_in_error(cp_index)) {
        TRACE2("resolve.testing", "Constant pool entry " << cp_index << " already contains error.");
        unlock();
        return NULL;
    }

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

    const String* classname = cp.get_utf8_string(cp.get_class_name_index(cp_index));
    unlock();

    // load the class in
    Class* other_clss = m_class_loader->LoadVerifyAndPrepareClass(env, classname);
    if(other_clss == NULL)
    {
        // FIXMECL should find out if this is VirtualMachineError
        assert(exn_raised());
        class_report_failure(this, cp_index, exn_get());
        exn_clear();
        return NULL;
    }

    // Check access control:
    //   referenced class should be public,
    //   or referenced class & declaring class are the same,
    //   or referenced class & declaring class are in the same runtime package,
    //   or declaring class not checked
    //   (the last case is needed for certain magic classes,
    //   eg, reflection implementation)
    if(m_can_access_all
        || other_clss->is_public()
        || other_clss == this
        || m_package == other_clss->m_package)
    {
        lock();
        cp.resolve_entry(cp_index, other_clss);
        unlock();
        return other_clss;
    }

    // Check access control for inner classes:
    //   access control checks is the same as for members
    if(strrchr(other_clss->get_name()->bytes, '$') != NULL
        && can_access_inner_class(env, other_clss))
    {
        lock();
        cp.resolve_entry(cp_index, other_clss);
        unlock();
        return other_clss;
    }

    CLASS_REPORT_FAILURE(this, cp_index, "java/lang/IllegalAccessError",
        "from " << get_name()->bytes << " to " << other_clss->get_name()->bytes);
    // IllegalAccessError
    return NULL;
} // Class::_resolve_class
Esempio n. 26
0
bool Class::load_ancestors(Global_Env* env)
{
    m_state = ST_LoadingAncestors;

    const String* superName = get_super_class_name();

    if(superName == NULL) {
        if(env->InBootstrap() || get_name() != env->JavaLangClass_String) {
            // This class better be java.lang.Object
            if(get_name() != env->JavaLangObject_String) {
                // ClassFormatError
                std::stringstream ss;
                ss << get_name()->bytes
                    << ": class does not have superclass "
                    << "but the class is not java.lang.Object";
                REPORT_FAILED_CLASS_CLASS(m_class_loader, this,
                    "java/lang/ClassFormatError", ss.str().c_str());
                return false;
            }
        }
    } else {
        // Load super class
        Class* superClass;
        m_super_class.name = NULL;
        superClass = m_class_loader->LoadVerifyAndPrepareClass(env, superName);
        if(superClass == NULL) {
            assert(exn_raised());
            return false;
        }

        if(superClass->is_interface()) {
            REPORT_FAILED_CLASS_CLASS(m_class_loader, this,
                "java/lang/IncompatibleClassChangeError",
                "class " << m_name->bytes << " has interface "
                << superClass->get_name()->bytes << " as super class");
            return false;
        }
        if(superClass->is_final()) {
            REPORT_FAILED_CLASS_CLASS(m_class_loader, this,
                "java/lang/VerifyError",
                m_name->bytes << " cannot inherit from final class "
                << superClass->get_name()->bytes);
            return false;
        }

        // super class was successfully loaded
        m_super_class.clss = superClass;
        if(m_super_class.cp_index) {
            m_const_pool.resolve_entry(m_super_class.cp_index, superClass);
        }

        // if it's an interface, its superclass must be java/lang/Object
        if(is_interface()) {
            if((env->JavaLangObject_Class != NULL) && (superClass != env->JavaLangObject_Class)) {
                std::stringstream ss;
                ss << get_name()->bytes << ": interface superclass is not java.lang.Object";
                REPORT_FAILED_CLASS_CLASS(m_class_loader, this,
                    "java/lang/ClassFormatError", ss.str().c_str());
                return false;
            }
        }

        // Update the cha_first_child and cha_next_sibling fields.
        m_cha_first_child = NULL;
        if(has_super_class())
        {
            m_cha_next_sibling = get_super_class()->m_cha_first_child;
            get_super_class()->m_cha_first_child = this;
        }
    }

    //
    // load in super interfaces
    //
    for(unsigned i = 0; i < m_num_superinterfaces; i++ ) {
        const String* intfc_name = m_superinterfaces[i].name;
        Class* intfc = m_class_loader->LoadVerifyAndPrepareClass(env, intfc_name);
        if(intfc == NULL) {
            assert(exn_raised());
            return false;
        }
        if(!intfc->is_interface()) {
            REPORT_FAILED_CLASS_CLASS(m_class_loader, this,
                "java/lang/IncompatibleClassChangeError",
                get_name()->bytes << ": " << intfc->get_name()->bytes
                << " is not an interface");
            return false;
        }

        // superinterface was successfully loaded
        m_superinterfaces[i].clss = intfc;
        if(m_superinterfaces[i].cp_index != 0) {
            // there are no constant pool entries for array classes
            m_const_pool.resolve_entry(m_superinterfaces[i].cp_index, intfc);
        }
    }
    // class, superclass, and superinterfaces successfully loaded

    m_state = ST_Loaded;
    if(!is_array())
        m_package = m_class_loader->ProvidePackage(env, m_name, NULL);

    return true;
}
Esempio n. 27
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;
}
Esempio n. 28
0
/*
 * Class:     java_lang_VMClassRegistry
 * Method:    getSystemPackages
 * Signature: (I)[[Ljava/lang/String;
 */
JNIEXPORT jobjectArray JNICALL Java_java_lang_VMClassRegistry_getSystemPackages
  (JNIEnv *jenv, jclass, jint len)
{
    Global_Env* genv = VM_Global_State::loader_env;
    ClassLoader* cl = static_cast<ClassLoader*>
        (genv->bootstrap_class_loader);
    Package_Table* ptab = cl->getPackageTable();
    cl->Lock();
    unsigned p_num = (unsigned)ptab->size();
    if (p_num == (unsigned)len) 
    {
        cl->Unlock();
        return NULL;
    }
    const char ** pkgs = (const char **)STD_MALLOC(p_num * 2 * sizeof(char*));
    size_t buf_len = 0;
    unsigned index = 0;
    for (Package_Table::const_iterator it = ptab->begin(), end = ptab->end(); 
        it != end; ++it)
    {
        const char* name = pkgs[index++] = (*it).first->bytes;
        pkgs[index++] = (*it).second->get_jar();
        size_t name_len = (*it).first->len;
        if (name_len > buf_len) {
            buf_len = name_len;
        }
    }
    cl->Unlock();

    jclass string_class = struct_Class_to_java_lang_Class_Handle(genv->JavaLangString_Class);
    static Class* aos = genv->LoadCoreClass("[Ljava/lang/String;");
    jclass string_array_class = struct_Class_to_java_lang_Class_Handle(aos);
    assert(string_class);
    assert(string_array_class);
        
    jobjectArray result = NewObjectArray(jenv, p_num, string_array_class, NULL);
    if (result) 
    {
        char* buf = (char*)STD_MALLOC(buf_len + 1);
        p_num *= 2;
        for (index = 0; index < p_num; )
        {
            jobjectArray pair = NewObjectArray(jenv, 2, string_class, NULL);
            if (!pair) {
                break;
            }
            SetObjectArrayElement(jenv, result, index/2, pair);

            char* name = strcpy(buf, pkgs[index++]);
            for (char* c = name; *c != '\0'; ++c) {
                if (*c == '/') {
                    *c = '.';
                }
            }
            jstring jname = NewStringUTF(jenv, name);
            if (!jname) {
                break;
            }
            SetObjectArrayElement(jenv, pair, 0, jname);

            const char * jar = pkgs[index++];
            if (jar) {
                jstring js = NewStringUTF(jenv, jar);
                if (!js) break;
                SetObjectArrayElement(jenv, pair, 1, js);
            }
        }
        STD_FREE(buf);
    }

    STD_FREE(pkgs);
    
    assert(result || exn_raised());
    return result;
}