Пример #1
0
//
// resolve constant pool reference to a method
// used for invokespecial
//
Method* resolve_special_method_env(Global_Env *env,
                                    Class_Handle curr_clss,
                                    unsigned index,
                                    bool raise_exn)
{
    ASSERT_RAISE_AREA;

    Method* method = curr_clss->_resolve_method(env, index);
    if(!method) {
        assert(curr_clss->get_constant_pool().is_entry_in_error(index));
        if (raise_exn) {
            exn_raise_object(curr_clss->get_constant_pool().get_error_cause(index));
        }
        return NULL;
    }
    if(curr_clss->is_super()
        && is_class_extended_class(curr_clss->get_super_class(), method->get_class())
        && method->get_name() != env->Init_String)
    {
        Method* result_meth;
        for(Class* clss = curr_clss->get_super_class(); clss; clss = clss->get_super_class())
        {
            result_meth = clss->lookup_method(method->get_name(), method->get_descriptor());
            if(result_meth) {
                method = result_meth;
                break;
            }
        }
    }
    if(method && !method_can_link_special(curr_clss, index, method, raise_exn))
        return NULL;
    return method;
} //resolve_special_method_env
Пример #2
0
/*
 * Get Method Name (and Signature)
 *
 * For the method indicated by method, return the method name via
 * name_ptr and method signature via signature_ptr.
 *
 * REQUIRED Functionality.
 */
jvmtiError JNICALL
jvmtiGetMethodName(jvmtiEnv* env,
                   jmethodID method,
                   char** name_ptr,
                   char** signature_ptr,
                   char** generic_ptr)
{
    TRACE("GetMethodName called");
    SuspendEnabledChecker sec;
    /*
     * Check given env & current phase.
     */
    jvmtiPhase phases[] = {JVMTI_PHASE_START, JVMTI_PHASE_LIVE};

    CHECK_EVERYTHING();

    if( !method ) return JVMTI_ERROR_NULL_POINTER;
    // Either name_ptr, signature_ptr, or generic_ptr can be NULL
    // In this case they are not returned

    char* mtd_name;
    char* mtd_sig;
    Method* mtd = reinterpret_cast<Method*>(method);
    jvmtiError err;
    if( name_ptr )
    {
        const String* name = mtd->get_name();
        err = _allocate(name->len + 1, (unsigned char**)(&mtd_name));
        if(err != JVMTI_ERROR_NONE)
            return err;
        // copy method name
        strcpy(mtd_name, name->bytes);
        *name_ptr = mtd_name;
    }

    if( signature_ptr )
    {
        const String* sig = mtd->get_descriptor();
        err = _allocate(sig->len + 1, (unsigned char**)(&mtd_sig));
        if(err != JVMTI_ERROR_NONE)
        {
            if(name_ptr && mtd_name)
                _deallocate((unsigned char*)mtd_name);
            return err;
        }
        // copy method signature
        strcpy(mtd_sig, sig->bytes);
        *signature_ptr = mtd_sig;
    }

    // ppervov: no generics support in VM as of yet
    if( generic_ptr )
        *generic_ptr = NULL;

    return JVMTI_ERROR_NONE;
}
Пример #3
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
Пример #4
0
void Method::_set_nop()
{
    bool verbose = false;

    Global_Env *env = VM_Global_State::loader_env;
    if (get_name() != env->Init_String || get_descriptor() != env->VoidVoidDescriptor_String) {
        return;
    }

    if(is_native()) {
        return;
    }
    unsigned len = _byte_code_length;
    if(!len) {
        return;
    }
    U_8* bc = _byte_codes;
    Nop_Stack_State stack_state = NS_StackEmpty;
    if(verbose) {
        printf("=========== nop[%d]: %s.%s%s\n", len, get_class()->get_name()->bytes, get_name()->bytes, get_descriptor()->bytes);
    }
    for (unsigned idx = 0; idx < len; idx++) {
        U_8 b = bc[idx];
        if(verbose) {
            printf("\tbc[%d]=%d, state=%d\n", idx, b, stack_state);
        }
        if(b == 0xb1) {   // return
            if(verbose) {
                printf("+++++++ nop: %s.%s%s\n", get_class()->get_name()->bytes, get_name()->bytes, get_descriptor()->bytes);
            }
            _flags.is_nop = TRUE;
            return;
        }
        switch(stack_state) {
        case NS_StackEmpty:
            switch(b) {
            case 0x2a:  // aload_0
                stack_state = NS_ThisPushed;
                break;
            default:
                return;
            }
            break;
        case NS_ThisPushed:
            switch(b) {
            case 0x01:  // aconst_null
            case 0x03:  // iconst_0
                stack_state = NS_ThisAndZeroPushed;
                break;
            case 0xb7:  // invokespecial
                {
                    unsigned index = (bc[idx + 1] << 8) + bc[idx + 2];
                    if(verbose) {
                        printf("\tinvokespecial, index=%d\n", index);
                    }
                    Method_Handle mh = resolve_special_method_env(VM_Global_State::loader_env,
                                                                  get_class(),
                                                                  index, false);
                    Method *callee = (Method *)mh;
                    if(!callee) {
                        if(verbose) {
                            printf("\tinvokespecial, callee==null\n");
                        }
                        return;
                    }
                    if(callee == this) {
                        return;
                    }
                    if(verbose) {
                        printf("invokespecial: %s.%s%s\n", callee->get_class()->get_name()->bytes, callee->get_name()->bytes, callee->get_descriptor()->bytes);
                    }
                    if(!callee->is_nop()) {
                        return;
                    }
                    const char *descr = callee->get_descriptor()->bytes;
                    if(descr[1] != ')') {
                        return;
                    }
                    if(verbose) {
                        printf("invokespecial nop: %s.%s%s\n", callee->get_class()->get_name()->bytes, callee->get_name()->bytes, callee->get_descriptor()->bytes);
                    }
                }
                stack_state = NS_StackEmpty;
                idx += 2;
                break;
            default:
                return;
            }
            break;
        case NS_ThisAndZeroPushed:
            switch(b) {
            case 0xb5:  // putfield
                stack_state = NS_StackEmpty;
                if(verbose) {
                    printf("\tputfield\n");
                }
                idx += 2;
                break;
            default:
                return;
            }
            break;
        default:
            LDIE(57, "Unexpected stack state");
            return;
        }
    }
    LDIE(56, "should'nt get here");
} //Method::_set_nop
Пример #5
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;
}
Пример #6
0
void
JIT_execute_method_default(JIT_Handle jh, 
                           jmethodID   methodID,
                           jvalue   *return_value,
                           jvalue   *args)
{
    //assert(("Doesn't compile", 0));
    //abort();
#if 1
    Method *meth = (Method*) methodID;
    assert(!hythread_is_suspend_enabled());
    void *entry_point = meth->get_code_addr();
    int nargs = meth->get_num_args();
    uint64 arg_words[255];
    int double_nargs = 0;
    double double_args[8];
    int num_arg_words = 0;
    int arg_num = 0;
    int num_ref_args = 0;
    Arg_List_Iterator iter = meth->get_argument_list();
    uint64 i64;
    Java_Type typ;
    char msg[300];
    if(!meth->is_static()) {
        ObjectHandle h = (ObjectHandle) args[arg_num++].l;
        // this pointer
        i64 = 0;
        if (h) i64 = (uint64) h->object;
        if (VM_Global_State::loader_env->compress_references) {
            // 20030318 We are in unmanaged code where null is represented by 0/NULL. Convert a null reference
            // to the representation of null in managed code (heap_base).
            if (i64 == 0) {
                i64 = (uint64)VM_Global_State::loader_env->heap_base;
            }
        }
        arg_words[num_arg_words++] = i64;
        num_ref_args++;
    }
    while((typ = curr_arg(iter)) != JAVA_TYPE_END) {
        ObjectHandle h;
        *msg = '\0';
        switch(typ) {
        case JAVA_TYPE_LONG:
            i64 = args[arg_num++].j;
            arg_words[num_arg_words++] = i64;
            break;
        case JAVA_TYPE_CLASS:
        case JAVA_TYPE_ARRAY:
            h = (ObjectHandle) args[arg_num++].l;
            i64 = 0;
            if (h) i64 = (uint64) h->object;
            if (VM_Global_State::loader_env->compress_references) {
                // 20030318 We are in unmanaged code where null is represented by 0/NULL. Convert a null reference
                // to the representation of null in managed code (heap_base).
                if (i64 == 0) {
                    i64 = (uint64)VM_Global_State::loader_env->heap_base;
                }
            }
            arg_words[num_arg_words++] = i64;
            num_ref_args++;
#ifdef _DEBUG
            {
                if (! VM_Global_State::loader_env->compress_references ||
                    i64 != (uint64)VM_Global_State::loader_env->heap_base) {
                    ManagedObject *object = (ManagedObject *)i64;
                    if(object) {
                        Class *clss = object->vt()->clss;
                        sprintf(msg, " of class '%s'", clss->get_name()->bytes);
                    }
                }
            }
#endif
            break;
        case JAVA_TYPE_SHORT:
            i64 = (uint64)args[arg_num++].s;
            arg_words[num_arg_words++] = i64;
            break;
        case JAVA_TYPE_CHAR:
            i64 = (uint64)args[arg_num++].c;
            arg_words[num_arg_words++] = i64;
            break;
        case JAVA_TYPE_BYTE:
            i64 = (uint64)args[arg_num++].b;
            arg_words[num_arg_words++] = i64;
            break;
        case JAVA_TYPE_BOOLEAN:
            i64 = (uint64)args[arg_num++].z;
            arg_words[num_arg_words++] = i64;
            break;
        case JAVA_TYPE_DOUBLE:
            double_args[double_nargs] = args[arg_num++].d;
            double_nargs++;
            break;
        case JAVA_TYPE_FLOAT:
            double_args[double_nargs] = (double)args[arg_num++].f;
            double_nargs++;
            break;
        default:
            i64 = (uint64)args[arg_num++].i;
            arg_words[num_arg_words++] = i64;
            break;
        }
        iter = advance_arg_iterator(iter);
    }

    // assert(nargs <= 8);
    double double_result;

    static void* addr_execute = get_vm_execute_java_method();
    struct{
        void* fun;
        void* gp;
    } fptr;
    fptr.fun = addr_execute;
    fptr.gp = get_vm_gp_value();
        // gashiman - changed _cdecl to __cdecl to work on linux
    uint64 (__cdecl *fpp_exec)(void *entry_point, int nargs, uint64 args[], 
        double *double_result_addr, int double_nargs, double double_args[], 
        void *thread_pointer, uint64 tid) = (uint64 (__cdecl * )(void *entry_point, int nargs, uint64 args[],
        double *double_result_addr, int double_nargs, double double_args[], 
        void *thread_pointer, uint64 tid))&fptr;
    IDATA id = hythread_get_self_id();
    uint64 int_result = (uint64)fpp_exec(entry_point, nargs, arg_words, &double_result,
        double_nargs, double_args, p_TLS_vmthread, id);

    // Save the result
    Java_Type ret_type = meth->get_return_java_type();
    switch(ret_type) {
    case JAVA_TYPE_VOID:
        break;
    case JAVA_TYPE_ARRAY:
    case JAVA_TYPE_CLASS:
        {
            ObjectHandle h = 0;
            if (VM_Global_State::loader_env->compress_references) {
                // 20030318 Convert a null reference in managed code (represented by heap_base)
                // to the representation of null in unmanaged code (0 or NULL).
                if ((uint64)int_result == (uint64)VM_Global_State::loader_env->heap_base) {
                    int_result = 0;
                } 
            }
            if (int_result) {
                h = oh_allocate_local_handle();
                h->object = (ManagedObject*) int_result;
            }
            return_value->l = h;
        }
        break;
    case JAVA_TYPE_LONG:
        return_value->j = int_result;
        break;
    case JAVA_TYPE_INT:
        *((I_32 *)return_value) = (I_32) int_result;
        break;
    case JAVA_TYPE_SHORT:
        *((int16 *)return_value) = (int16) int_result;
        break;
    case JAVA_TYPE_CHAR:
        *((uint16 *)return_value) = (uint16) int_result;
        break;
    case JAVA_TYPE_BYTE:
        *((I_8 *)return_value) = (I_8) int_result;
        break;
    case JAVA_TYPE_BOOLEAN:
        *((U_8 *)return_value) = (U_8) int_result;
        break;
    case JAVA_TYPE_DOUBLE:
        *((double *)return_value) = double_result;
        break;
    case JAVA_TYPE_FLOAT:
        *((float *)return_value) = (float) double_result;
        break;
    default:
#ifdef _DEBUG
        std::clog << "Returned to C from "
               << meth->get_class()->get_name()->bytes << "." << meth->get_name()->bytes
               << meth->get_descriptor()->bytes << "\n";
#endif
        //DIE("Return type ");// <<  (int)ret_type << " is not implemented\n");
        std::clog << "Return type " <<  (int)ret_type << " is not implemented\n";
    }
#endif

} //vm_execute_java_method_array