/* * Get Method Modifiers * * For the method indicated by method, return the access flags * via modifiers_ptr. * * REQUIRED Functionality. */ jvmtiError JNICALL jvmtiGetMethodModifiers(jvmtiEnv* env, jmethodID method, jint* modifiers_ptr) { TRACE("GetMethodModifiers 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; if( !modifiers_ptr ) return JVMTI_ERROR_NULL_POINTER; *modifiers_ptr = 0; Method* mtd = reinterpret_cast<Method*>(method); if( mtd->is_public() ) *modifiers_ptr |= ACC_PUBLIC; if( mtd->is_private() ) *modifiers_ptr |= ACC_PRIVATE; if( mtd->is_protected() ) *modifiers_ptr |= ACC_PROTECTED; if( mtd->is_static() ) *modifiers_ptr |= ACC_STATIC; if( mtd->is_final() ) *modifiers_ptr |= ACC_FINAL; if( mtd->is_synchronized() ) *modifiers_ptr |= ACC_SYNCHRONIZED; if( mtd->is_native() ) *modifiers_ptr |= ACC_NATIVE; if( mtd->is_abstract() ) *modifiers_ptr |= ACC_ABSTRACT; return JVMTI_ERROR_NONE; }
// Find all methods on this hierarchy that match this // method's erased (name, signature) bool visit() { PseudoScope* scope = PseudoScope::cast(current_data()); InstanceKlass* iklass = current_class(); Method* m = iklass->find_method(_method_name, _method_signature); // private interface methods are not candidates for default methods // invokespecial to private interface methods doesn't use default method logic // The overpasses are your supertypes' errors, we do not include them // future: take access controls into account for superclass methods if (m != NULL && !m->is_static() && !m->is_overpass() && (!iklass->is_interface() || m->is_public())) { if (_family == NULL) { _family = new StatefulMethodFamily(); } if (iklass->is_interface()) { StateRestorer* restorer = _family->record_method_and_dq_further(m); scope->add_mark(restorer); } else { // This is the rule that methods in classes "win" (bad word) over // methods in interfaces. This works because of single inheritance _family->set_target_if_empty(m); } } return true; }
void CodeInstaller::pd_relocate_JavaMethod(Handle hotspot_method, jint pc_offset, TRAPS) { #ifdef ASSERT Method* method = NULL; // we need to check, this might also be an unresolved method if (hotspot_method->is_a(HotSpotResolvedJavaMethodImpl::klass())) { method = getMethodFromHotSpotMethod(hotspot_method()); } #endif switch (_next_call_type) { case INLINE_INVOKE: break; case INVOKEVIRTUAL: case INVOKEINTERFACE: { assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface"); NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_virtual_call_stub()); _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc), Assembler::call32_operand); break; } case INVOKESTATIC: { assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic"); NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_static_call_stub()); _instructions->relocate(call->instruction_address(), relocInfo::static_call_type, Assembler::call32_operand); break; } case INVOKESPECIAL: { assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial"); NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub()); _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type, Assembler::call32_operand); break; } default: JVMCI_ERROR("invalid _next_call_type value"); break; } }
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; }
static GrowableArray<EmptyVtableSlot*>* find_empty_vtable_slots( InstanceKlass* klass, GrowableArray<Method*>* mirandas, TRAPS) { assert(klass != NULL, "Must be valid class"); GrowableArray<EmptyVtableSlot*>* slots = new GrowableArray<EmptyVtableSlot*>(); // All miranda methods are obvious candidates for (int i = 0; i < mirandas->length(); ++i) { Method* m = mirandas->at(i); if (!already_in_vtable_slots(slots, m)) { slots->append(new EmptyVtableSlot(m)); } } // Also any overpasses in our superclasses, that we haven't implemented. // (can't use the vtable because it is not guaranteed to be initialized yet) InstanceKlass* super = klass->java_super(); while (super != NULL) { for (int i = 0; i < super->methods()->length(); ++i) { Method* m = super->methods()->at(i); if (m->is_overpass() || m->is_static()) { // m is a method that would have been a miranda if not for the // default method processing that occurred on behalf of our superclass, // so it's a method we want to re-examine in this new context. That is, // unless we have a real implementation of it in the current class. Method* impl = klass->lookup_method(m->name(), m->signature()); if (impl == NULL || impl->is_overpass() || impl->is_static()) { if (!already_in_vtable_slots(slots, m)) { slots->append(new EmptyVtableSlot(m)); } } } } // also any default methods in our superclasses if (super->default_methods() != NULL) { for (int i = 0; i < super->default_methods()->length(); ++i) { Method* m = super->default_methods()->at(i); // m is a method that would have been a miranda if not for the // default method processing that occurred on behalf of our superclass, // so it's a method we want to re-examine in this new context. That is, // unless we have a real implementation of it in the current class. Method* impl = klass->lookup_method(m->name(), m->signature()); if (impl == NULL || impl->is_overpass() || impl->is_static()) { if (!already_in_vtable_slots(slots, m)) { slots->append(new EmptyVtableSlot(m)); } } } } super = super->java_super(); } #ifndef PRODUCT if (TraceDefaultMethods) { tty->print_cr("Slots that need filling:"); streamIndentor si(tty); for (int i = 0; i < slots->length(); ++i) { tty->indent(); slots->at(i)->print_on(tty); tty->cr(); } } #endif // ndef PRODUCT return slots; }
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