/* * Get Current Thread CPU Time * * Return the CPU time utilized by the current thread. * * OPTIONAL Functionality. */ jvmtiError JNICALL jvmtiGetCurrentThreadCpuTime(jvmtiEnv* env, jlong* nanos_ptr) { TRACE2("jvmti.timer", "GetCurrentThreadCpuTime called"); IDATA status; SuspendEnabledChecker sec; /* * Check given env & current phase. */ jvmtiPhase phases[] = {JVMTI_PHASE_START, JVMTI_PHASE_LIVE}; CHECK_EVERYTHING(); CHECK_CAPABILITY(can_get_current_thread_cpu_time); if (NULL == nanos_ptr) return JVMTI_ERROR_NULL_POINTER; status = jthread_get_thread_cpu_time(NULL, nanos_ptr); if (status != TM_ERROR_NONE) return JVMTI_ERROR_INTERNAL; return JVMTI_ERROR_NONE; }
/* * Is Method Synthetic * * For the method indicated by method, return a value indicating * whether the method is synthetic via is_synthetic_ptr. Synthetic * methods are generated by the compiler but not present in the * original source code. * * OPTIONAL Functionality. */ jvmtiError JNICALL jvmtiIsMethodSynthetic(jvmtiEnv* env, jmethodID method, jboolean* is_synthetic_ptr) { TRACE("IsMethodSynthetic called"); SuspendEnabledChecker sec; /* * Check given env & current phase. */ jvmtiPhase phases[] = {JVMTI_PHASE_START, JVMTI_PHASE_LIVE}; CHECK_EVERYTHING(); CHECK_CAPABILITY(can_get_synthetic_attribute); /** * Check is_synthetic_ptr */ if( !is_synthetic_ptr ) { return JVMTI_ERROR_NULL_POINTER; } /** * Check method */ if( !method ) { return JVMTI_ERROR_INVALID_METHODID; } /** * Get method synthetic */ *is_synthetic_ptr = (jboolean)(reinterpret_cast<Method*>(method)->is_synthetic() ? JNI_TRUE : JNI_FALSE); return JVMTI_ERROR_NONE; } // jvmtiIsMethodSynthetic
/* * Get Method Location * * For the method indicated by method, return the beginning and * ending addresses through start_location_ptr and end_location_ptr. * In a conventional byte code indexing scheme, start_location_ptr * will always point to zero and end_location_ptr will always * point to the byte code count minus one. * * REQUIRED Functionality. */ jvmtiError JNICALL jvmtiGetMethodLocation(jvmtiEnv* env, jmethodID method, jlocation* start_location_ptr, jlocation* end_location_ptr) { TRACE("GetMethodLocation called"); SuspendEnabledChecker sec; /* * Check given env & current phase. */ jvmtiPhase phases[] = {JVMTI_PHASE_START, JVMTI_PHASE_LIVE}; CHECK_EVERYTHING(); /** * Check start_location_ptr and end_location_ptr */ if( !start_location_ptr || !end_location_ptr ) return JVMTI_ERROR_NULL_POINTER; /** * Check start_location_ptr and end_location_ptr */ if( !method ) return JVMTI_ERROR_NULL_POINTER; *start_location_ptr = 0; *end_location_ptr = reinterpret_cast<Method*>(method)->get_byte_code_size()-1; return JVMTI_ERROR_NONE; }
/* * Is Method Obsolete * * Has this method been made obsolete with RedefineClasses? * * REQUIRED Functionality. */ jvmtiError JNICALL jvmtiIsMethodObsolete(jvmtiEnv* env, jmethodID method, jboolean* is_obsolete_ptr) { TRACE("IsMethodObsolete called for " << method); SuspendEnabledChecker sec; /* * Check given env & current phase. */ jvmtiPhase phases[] = {JVMTI_PHASE_START, JVMTI_PHASE_LIVE}; CHECK_EVERYTHING(); CHECK_CAPABILITY(can_redefine_classes); /** * Check is_obsolete_ptr */ if( !is_obsolete_ptr ) { return JVMTI_ERROR_NULL_POINTER; } /** * Check method */ if( !method ) { return JVMTI_ERROR_INVALID_METHODID; } /** * Since we don't have RedefineClasses yet, always return false */ *is_obsolete_ptr = JNI_FALSE; TRACE("IsMethodObsolete(" << method << ") = " << *is_obsolete_ptr); return JVMTI_ERROR_NONE; } // jvmtiIsMethodObsolete
/* * Is Method Native * * For the method indicated by method, return a value indicating * whether the method is native via is_native_ptr * * REQUIRED Functionality. */ jvmtiError JNICALL jvmtiIsMethodNative(jvmtiEnv* env, jmethodID method, jboolean* is_native_ptr) { TRACE("IsMethodNative called for " << method); SuspendEnabledChecker sec; /* * Check given env & current phase. */ jvmtiPhase phases[] = {JVMTI_PHASE_START, JVMTI_PHASE_LIVE}; CHECK_EVERYTHING(); /** * Check is_native_ptr */ if( !is_native_ptr ) { return JVMTI_ERROR_NULL_POINTER; } /** * Check method */ if( !method ) { return JVMTI_ERROR_INVALID_METHODID; } *is_native_ptr = (jboolean)(reinterpret_cast<Method*>(method)->is_native()?JNI_TRUE:JNI_FALSE); TRACE("IsMethodNative(" << method << ") = " << *is_native_ptr); return JVMTI_ERROR_NONE; }
/* * Get Method Declaring Class * * For the method indicated by method, return the class that * defined it via declaring_class_ptr. * * REQUIRED Functionality. */ jvmtiError JNICALL jvmtiGetMethodDeclaringClass(jvmtiEnv* env, jmethodID method, jclass* declaring_class_ptr) { TRACE("GetMethodDeclaringClass called for " << method); SuspendEnabledChecker sec; /* * Check given env & current phase. */ jvmtiPhase phases[] = {JVMTI_PHASE_START, JVMTI_PHASE_LIVE}; CHECK_EVERYTHING(); if( !method ) return JVMTI_ERROR_INVALID_FIELDID; if( !declaring_class_ptr ) return JVMTI_ERROR_NULL_POINTER; Method* mtd = (Method*)method; Class* cls = mtd->get_class(); ObjectHandle hclss = struct_Class_to_java_lang_Class_Handle(cls); ObjectHandle newH = NewLocalRef(p_TLS_vmthread->jni_env, hclss); *declaring_class_ptr = (jclass)newH; return JVMTI_ERROR_NONE; }
/* * 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; }
/* * Get Bytecodes * * For the method indicated by method, return the byte codes that * implement the method. The number of bytecodes is returned via * bytecode_count_ptr. The byte codes themselves are returned via * bytecodes_ptr. * * OPTIONAL Functionality. */ jvmtiError JNICALL jvmtiGetBytecodes(jvmtiEnv* env, jmethodID method, jint* bytecode_count_ptr, unsigned char** bytecodes_ptr) { TRACE("GetBytecodes called"); SuspendEnabledChecker sec; /* * Check given env & current phase. */ jvmtiPhase phases[] = {JVMTI_PHASE_START, JVMTI_PHASE_LIVE}; CHECK_EVERYTHING(); CHECK_CAPABILITY(can_get_bytecodes); /** * Check is_native_ptr */ if( !bytecode_count_ptr || !bytecodes_ptr ) { return JVMTI_ERROR_NULL_POINTER; } /** * Check method */ if( !method ) { return JVMTI_ERROR_INVALID_METHODID; } Method* mtd = (Method*)method; if( mtd->is_native() ) return JVMTI_ERROR_NATIVE_METHOD; if( mtd->get_byte_code_addr() == NULL ) return JVMTI_ERROR_OUT_OF_MEMORY; *bytecode_count_ptr = mtd->get_byte_code_size(); jvmtiError err = _allocate( *bytecode_count_ptr, bytecodes_ptr ); if( err != JVMTI_ERROR_NONE ) return err; memcpy( *bytecodes_ptr, mtd->get_byte_code_addr(), *bytecode_count_ptr ); if (interpreter_enabled()) { TIEnv *p_env = (TIEnv *)env; VMBreakPoints* vm_brpt = p_env->vm->vm_env->TI->vm_brpt; LMAutoUnlock lock(vm_brpt->get_lock()); for (VMBreakPoint* bpt = vm_brpt->find_method_breakpoint(method); bpt; bpt = vm_brpt->find_next_method_breakpoint(bpt, method)) { (*bytecodes_ptr)[bpt->location] = (unsigned char)bpt->saved_byte; } } return JVMTI_ERROR_NONE; }
/* * Get Thread CPU Time * * Return the CPU time utilized by the specified thread. * * OPTIONAL Functionality. */ jvmtiError JNICALL jvmtiGetThreadCpuTime(jvmtiEnv* env, jthread thread, jlong* nanos_ptr) { TRACE2("jvmti.timer", "GetThreadCpuTime called"); IDATA status; SuspendEnabledChecker sec; /* * Check given env & current phase. */ jvmtiPhase phases[] = {JVMTI_PHASE_LIVE}; CHECK_EVERYTHING(); CHECK_CAPABILITY(can_get_thread_cpu_time); if (NULL == nanos_ptr) return JVMTI_ERROR_NULL_POINTER; if (NULL == thread) { status = jthread_get_thread_cpu_time(NULL, nanos_ptr); } else { if (! is_valid_thread_object(thread)) return JVMTI_ERROR_INVALID_THREAD; // lock thread manager to avoid occasional change of thread state hythread_global_lock(); int state;// =thread_get_thread_state(thread); jvmtiError err = jvmtiGetThreadState(env, thread, &state); if (err != JVMTI_ERROR_NONE){ return err; } switch (state) { case JVMTI_THREAD_STATE_TERMINATED: // thread is terminated case JVMTI_JAVA_LANG_THREAD_STATE_NEW: // thread is new hythread_global_unlock(); return JVMTI_ERROR_THREAD_NOT_ALIVE; default: // thread is alive status = jthread_get_thread_cpu_time(thread, nanos_ptr); break; } hythread_global_unlock(); } if (status != TM_ERROR_NONE) return JVMTI_ERROR_INTERNAL; return JVMTI_ERROR_NONE; }
/* * 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; }
/* * Dispose Environment * * Shutdown a JVMTI connection created with JNI GetEnv (see JVMTI * Environments). Dispose of any resources held by the environment. * Suspended threads are not resumed, this must be done explicitly * by the agent. Allocated memory is not released, this must be * done explicitly by the agent. This environment may not be used * after this call. This call returns to the caller. * * REQUIRED Functionality. */ jvmtiError JNICALL jvmtiDisposeEnvironment(jvmtiEnv* env) { TRACE2("jvmti.general", "DisposeEnvironment called, env = " << env); SuspendEnabledChecker sec; /* * Check given env & current phase. */ jvmtiPhase* phases = NULL; CHECK_EVERYTHING(); TIEnv *p_env = (TIEnv *)env; DebugUtilsTI *ti = p_env->vm->vm_env->TI; LMAutoUnlock lock(&ti->TIenvs_lock); // Disable all global events for this environment int iii; for (iii = JVMTI_MIN_EVENT_TYPE_VAL; iii <= JVMTI_MAX_EVENT_TYPE_VAL; iii++) remove_event_from_global(env, (jvmtiEvent)iii); // Disable all thread local events for this environment, do it only in live phase // otherwise environment couldn't register for any thread local events // because it couldn't get any live thread references jvmtiPhase ph; jvmtiGetPhase(env, &ph); if (JVMTI_PHASE_LIVE == ph) { // FIXME: this loop is very ugly, could we improve it? jint threads_number; jthread *threads; jvmtiGetAllThreads(env, &threads_number, &threads); for (int jjj = 0; jjj < threads_number; jjj++) for (iii = JVMTI_MIN_EVENT_TYPE_VAL; iii <= JVMTI_MAX_EVENT_TYPE_VAL; iii++) remove_event_from_thread(env, (jvmtiEvent)iii, threads[jjj]); _deallocate((unsigned char *)threads); } // Remove all breakpoints set by this environment and release interface ti->vm_brpt->release_intf(p_env->brpt_intf); // Remove all capabilities for this environment jvmtiRelinquishCapabilities(env, &p_env->posessed_capabilities); // Remove environment from the global list p_env->vm->vm_env->TI->removeEnvironment(p_env); _deallocate((unsigned char *)env); return JVMTI_ERROR_NONE; }
/* * Set Environment Local Storage * * The VM stores a pointer value associated with each environment. * This pointer value is called environment-local storage. This * value is NULL unless set with this function. * * REQUIRED Functionality. */ jvmtiError JNICALL jvmtiSetEnvironmentLocalStorage(jvmtiEnv* env, const void* data) { TRACE("SetEnvironmentLocalStorage called, data = " << data); SuspendEnabledChecker sec; /* * Check given env & current phase. */ jvmtiPhase* phases = NULL; CHECK_EVERYTHING(); ((TIEnv *)env)->user_storage = const_cast<void*>(data); return JVMTI_ERROR_NONE; }
/* * Get Phase * * Return the current phase of VM execution. * * REQUIRED Functionality. */ jvmtiError JNICALL jvmtiGetPhase(jvmtiEnv* env, jvmtiPhase* phase_ptr) { TRACE2("jvmti.general", "GetPhase called"); SuspendEnabledChecker sec; /* * Check given env & current phase. */ jvmtiPhase* phases = NULL; CHECK_EVERYTHING(); if (NULL == phase_ptr) return JVMTI_ERROR_NULL_POINTER; *phase_ptr = ((TIEnv *)env)->vm->vm_env->TI->getPhase(); TRACE2("jvmti", "Phase = " << *phase_ptr); return JVMTI_ERROR_NONE; }
/* * Get Timer Information * * Get information about the GetTime timer. The fields of the * jvmtiTimerInfo structure are filled in with details about the * timer. This information will not change during a particular * invocation of the VM. * * REQUIRED Functionality. */ jvmtiError JNICALL jvmtiGetTimerInfo(jvmtiEnv* env, jvmtiTimerInfo* info_ptr) { TRACE2("jvmti.timer", "GetTimerInfo called"); SuspendEnabledChecker sec; /* * Check given env & current phase. */ jvmtiPhase* phases = NULL; CHECK_EVERYTHING(); if (NULL == info_ptr) return JVMTI_ERROR_NULL_POINTER; fill_timer_info(info_ptr); return JVMTI_ERROR_NONE; }
/* * Get Environment Local Storage * * Called by the agent to get the value of the JVMTI * environment-local storage * * REQUIRED Functionality. */ jvmtiError JNICALL jvmtiGetEnvironmentLocalStorage(jvmtiEnv* env, void** data_ptr) { TRACE2("jvmti.general", "GetEnvironmentLocalStorage called"); SuspendEnabledChecker sec; /* * Check given env & current phase. */ jvmtiPhase* phases = NULL; CHECK_EVERYTHING(); if (NULL == data_ptr) return JVMTI_ERROR_NULL_POINTER; *data_ptr = ((TIEnv *)env)->user_storage; return JVMTI_ERROR_NONE; }
/* * Get Version Number * * Return the JVMTI version via version_ptr. The return value is * the version identifier. The version identifier includes major, * minor and micro version as well as the interface type. * * REQUIRED Functionality. */ jvmtiError JNICALL jvmtiGetVersionNumber(jvmtiEnv* env, jint* version_ptr) { TRACE2("jvmti.general", "GetVersionNumber called"); SuspendEnabledChecker sec; /* * Check given env & current phase. */ jvmtiPhase* phases = NULL; CHECK_EVERYTHING(); if (NULL == version_ptr) return JVMTI_ERROR_NULL_POINTER; *version_ptr = JVMTI_VERSION; return JVMTI_ERROR_NONE; }
/* * Get Arguments Size * * For the method indicated by method, return via max_ptr the * number of local variable slots used by the method's arguments. * Note that two-word arguments use two slots * * REQUIRED Functionality. */ jvmtiError JNICALL jvmtiGetArgumentsSize(jvmtiEnv* env, jmethodID method, jint* size_ptr) { TRACE("GetArgumentsSize 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( !size_ptr ) return JVMTI_ERROR_NULL_POINTER; *size_ptr = reinterpret_cast<Method*>(method)->get_num_arg_slots(); return JVMTI_ERROR_NONE; }
/* * Get Available Processors * * Returns the number of processors available to the Java virtual * machine. * * REQUIRED Functionality. */ jvmtiError JNICALL jvmtiGetAvailableProcessors(jvmtiEnv* env, jint* processor_count_ptr) { TRACE2("jvmti.timer", "GetAvailableProcessors called"); SuspendEnabledChecker sec; /* * Check given env & current phase. */ jvmtiPhase* phases = NULL; CHECK_EVERYTHING(); if (processor_count_ptr == NULL) { return JVMTI_ERROR_NULL_POINTER; } *processor_count_ptr = port_CPUs_number(); return JVMTI_ERROR_NONE; }
/* * Get Thread CPU Timer Information * * Get information about the GetThreadCpuTime timer. The fields * of the jvmtiTimerInfo structure are filled in with details * about the timer. * * OPTIONAL Functionality. */ jvmtiError JNICALL jvmtiGetThreadCpuTimerInfo(jvmtiEnv* env, jvmtiTimerInfo* info_ptr) { TRACE2("jvmti.timer", "GetThreadCpuTimerInfo called"); SuspendEnabledChecker sec; /* * Check given env & current phase. */ jvmtiPhase phases[] = {JVMTI_PHASE_LIVE}; CHECK_EVERYTHING(); CHECK_CAPABILITY(can_get_thread_cpu_time); if (NULL == info_ptr) return JVMTI_ERROR_NULL_POINTER; fill_timer_info(info_ptr); return JVMTI_ERROR_NONE; }
/* * Get Time * * Return the current value of the system timer, in nanoseconds. * * REQUIRED Functionality. */ jvmtiError JNICALL jvmtiGetTime(jvmtiEnv* env, jlong* nanos_ptr) { TRACE2("jvmti.timer", "GetTime called"); SuspendEnabledChecker sec; /* * Check given env & current phase. */ jvmtiPhase* phases = NULL; CHECK_EVERYTHING(); if (nanos_ptr == NULL) { return JVMTI_ERROR_NULL_POINTER; } // get time in milliseconds apr_time_t apr_time = apr_time_now(); *nanos_ptr = ((jlong) apr_time) * 1000ULL; // convert to nanos return JVMTI_ERROR_NONE; }
jvmtiError JNICALL jvmtiGetLocalLong(jvmtiEnv* env, jthread thread, jint depth, jint slot, jlong* value_ptr) { TRACE("GetLocalLong called"); SuspendEnabledChecker sec; /* * Check given env & current phase. */ jvmtiPhase phases[] = {JVMTI_PHASE_LIVE}; CHECK_EVERYTHING(); CHECK_CAPABILITY(can_access_local_variables); // check error condition: JVMTI_ERROR_INVALID_THREAD // check error condition: JVMTI_ERROR_THREAD_NOT_ALIVE // check error condition: JVMTI_ERROR_ILLEGAL_ARGUMENT // check error condition: JVMTI_ERROR_NULL_POINTER jvmtiError err = GetLocal_checkArgs(env, &thread, depth, slot, value_ptr); if (err != JVMTI_ERROR_NONE) return err; bool thread_suspended = false; // Suspend thread before getting stacks vm_thread_t vm_thread; if (NULL != thread) { // Check that this thread is not current vm_thread = jthread_get_vm_thread_ptr_safe(thread); if (vm_thread != p_TLS_vmthread) { IDATA UNREF status = hythread_suspend_other((hythread_t)vm_thread); assert(TM_ERROR_NONE == status); thread_suspended = true; } } else vm_thread = p_TLS_vmthread; if (interpreter_enabled()) // check error condition: JVMTI_ERROR_INVALID_SLOT // check error condition: JVMTI_ERROR_OPAQUE_FRAME // check error condition: JVMTI_ERROR_NO_MORE_FRAMES // TODO: check error condition: JVMTI_ERROR_TYPE_MISMATCH err = interpreter.interpreter_ti_getLocal64(env, vm_thread, depth, slot, value_ptr); else { GET_JIT_FRAME_CONTEXT; tmn_suspend_disable(); OpenExeJpdaError result = jit->get_local_var(method, jfc, slot, VM_DATA_TYPE_INT64, value_ptr); si_free(si); tmn_suspend_enable(); err = jvmti_translate_jit_error(result); } if (thread_suspended) hythread_resume((hythread_t)vm_thread); return err; }
/** * General function to set value of local variable. * @param var_type type of the local variable * @param p_value pointer to the new variable value */ static jvmtiError set_local(jvmtiEnv* env, jthread thread, jint depth, jint slot, VM_Data_Type var_type, void* p_value) { SuspendEnabledChecker sec; /* * Check given env & current phase. */ jvmtiPhase phases[] = {JVMTI_PHASE_LIVE}; CHECK_EVERYTHING(); CHECK_CAPABILITY(can_access_local_variables); // check error condition: JVMTI_ERROR_INVALID_THREAD // check error condition: JVMTI_ERROR_THREAD_NOT_ALIVE // check error condition: JVMTI_ERROR_ILLEGAL_ARGUMENT jvmtiError err = GetLocal_checkArgs(env, &thread, depth, slot, p_value); if (err != JVMTI_ERROR_NONE) return err; // check error condition: JVMTI_ERROR_INVALID_OBJECT if (VM_DATA_TYPE_CLASS == var_type && ! is_valid_object(env, *(jobject*) p_value)) return JVMTI_ERROR_INVALID_OBJECT; bool thread_suspended = false; // Suspend thread before getting stacks vm_thread_t vm_thread; if (NULL != thread) { // Check that this thread is not current vm_thread = jthread_get_vm_thread_ptr_safe(thread); if (vm_thread != p_TLS_vmthread) { IDATA UNREF status = hythread_suspend_other((hythread_t)vm_thread); assert(TM_ERROR_NONE == status); thread_suspended = true; } } else vm_thread = p_TLS_vmthread; if (interpreter_enabled()) { // TODO: check error condition: JVMTI_ERROR_INVALID_SLOT // TODO: check error condition: JVMTI_ERROR_TYPE_MISMATCH // TODO: check error condition: JVMTI_ERROR_OPAQUE_FRAME // TODO: check error condition: JVMTI_ERROR_NO_MORE_FRAMES switch (var_type) { case VM_DATA_TYPE_CLASS: err = interpreter.interpreter_ti_setObject(env, vm_thread, depth, slot, *(jobject*) p_value); break; case VM_DATA_TYPE_INT32: case VM_DATA_TYPE_F4: err = interpreter.interpreter_ti_setLocal32(env, vm_thread, depth, slot, *(int*) p_value); break; case VM_DATA_TYPE_INT64: case VM_DATA_TYPE_F8: err = interpreter.interpreter_ti_setLocal64(env, vm_thread, depth, slot, *(int64*) p_value); break; default: DIE(("Error: unrecognized local variable type")); } } else { GET_JIT_FRAME_CONTEXT; tmn_suspend_disable(); OpenExeJpdaError result; switch (var_type) { case VM_DATA_TYPE_CLASS: if (NULL != *(jobject*) p_value) result = jit->set_local_var(method, jfc, slot, VM_DATA_TYPE_CLASS, &(*(ObjectHandle*) p_value)->object); else { ManagedObject *n = (ManagedObject *)VM_Global_State::loader_env->managed_null; result = jit->set_local_var(method, jfc, slot, VM_DATA_TYPE_CLASS, &n); } break; case VM_DATA_TYPE_INT32: case VM_DATA_TYPE_F4: case VM_DATA_TYPE_INT64: case VM_DATA_TYPE_F8: result = jit->set_local_var(method, jfc, slot, var_type, p_value); break; default: DIE(("Error: unrecognized local variable type")); } si_free(si); tmn_suspend_enable(); err = jvmti_translate_jit_error(result); } if (thread_suspended) hythread_resume((hythread_t)vm_thread); return err; }
/* * Get Line Number Table * * For the method indicated by method, return a table of source * line number entries. The size of the table is returned via * entry_count_ptr and the table itself is returned via table_ptr. * * OPTIONAL Functionality. */ jvmtiError JNICALL jvmtiGetLineNumberTable(jvmtiEnv* env, jmethodID method, jint* entry_count_ptr, jvmtiLineNumberEntry** table_ptr) { TRACE("GetLineNumberTable called"); SuspendEnabledChecker sec; int index, count; Method *method_ptr; jvmtiError result; /* * Check given env & current phase. */ jvmtiPhase phases[] = {JVMTI_PHASE_START, JVMTI_PHASE_LIVE}; CHECK_EVERYTHING(); CHECK_CAPABILITY(can_get_line_numbers); /** * Check entry_count_ptr and table_ptr */ if( !entry_count_ptr || !table_ptr ) { return JVMTI_ERROR_NULL_POINTER; } /** * Check method */ if( !method ) { return JVMTI_ERROR_INVALID_METHODID; } else if( ((Method*)method)->is_native() ) { return JVMTI_ERROR_NATIVE_METHOD; } /** * Get method line number table entries number */ method_ptr = (Method*)method; count = method_ptr->get_line_number_table_size(); if( count == 0 ) { return JVMTI_ERROR_ABSENT_INFORMATION; } /** * Allocate memory for line number table */ *entry_count_ptr = count; result = _allocate( count * sizeof(jvmtiLineNumberEntry), (unsigned char**)table_ptr ); if( result != JVMTI_ERROR_NONE ) { return result; } /** * Set line number table */ for( index = 0; index < count; ++index) { jvmtiLineNumberEntry* entry = *table_ptr + index; method_ptr->get_line_number_entry(index, &(entry->start_location), &(entry->line_number)); } return JVMTI_ERROR_NONE; } // jvmtiGetLineNumberTable
/* * Get Local Variable Table * * Return local variable information. * * OPTIONAL Functionality. */ jvmtiError JNICALL jvmtiGetLocalVariableTable(jvmtiEnv* env, jmethodID method, jint* entry_count_ptr, jvmtiLocalVariableEntry** table_ptr) { TRACE("GetLocalVariableTable called"); SuspendEnabledChecker sec; int len, index, count; char *pointer; Method *method_ptr; jvmtiError result; /* * Check given env & current phase. */ jvmtiPhase phases[] = {JVMTI_PHASE_LIVE}; CHECK_EVERYTHING(); CHECK_CAPABILITY(can_access_local_variables); /** * Check entry_count_ptr and table_ptr */ if( !entry_count_ptr || !table_ptr ) { return JVMTI_ERROR_NULL_POINTER; } /** * Check method */ if( !method ) { return JVMTI_ERROR_INVALID_METHODID; } else if( ((Method*)method)->is_native() ) { return JVMTI_ERROR_NATIVE_METHOD; } /** * Get method local variable table number entries */ method_ptr = (Method*)method; count = method_ptr->get_local_var_table_size(); if( count == 0 ) { return JVMTI_ERROR_ABSENT_INFORMATION; } /** * Allocate memory for local variable table */ *entry_count_ptr = count; result = _allocate( count * sizeof(jvmtiLocalVariableEntry), (unsigned char**)table_ptr ); if( result != JVMTI_ERROR_NONE ) { return result; } /** * Set local variable table */ for( index = 0; index < count; index++) { String *name, *type, *generic_type; jvmtiLocalVariableEntry* entry = *table_ptr + index; method_ptr->get_local_var_entry(index, &(entry->start_location), &(entry->length), &(entry->slot), &name, &type, &generic_type); // allocate memory for name len = get_utf8_length_of_8bit( (const U_8*)name->bytes, name->len); result = _allocate( len + 1, (unsigned char**)&pointer ); if( result != JVMTI_ERROR_NONE ) { return result; } // copy variable name utf8_from_8bit( pointer, (const U_8*)name->bytes, name->len); // set variable name entry->name = pointer; // allocate memory for signature len = get_utf8_length_of_8bit( (const U_8*)type->bytes, type->len); result = _allocate( len + 1, (unsigned char**)&pointer ); if( result != JVMTI_ERROR_NONE ) { return result; } // copy variable signature utf8_from_8bit( pointer, (const U_8*)type->bytes, type->len); // set variable signature entry->signature = pointer; // set variable slot if (generic_type) { // allocate memory for generic_signature len = get_utf8_length_of_8bit( (const U_8*)generic_type->bytes, generic_type->len); result = _allocate( len + 1, (unsigned char**)&pointer ); if( result != JVMTI_ERROR_NONE ) { return result; } // copy variable generic_signature utf8_from_8bit( pointer, (const U_8*)generic_type->bytes, generic_type->len); // set variable generic_signature entry->generic_signature = pointer; } else { entry->generic_signature = NULL; } } return JVMTI_ERROR_NONE; } // jvmtiGetLocalVariableTable