STATIC mp_obj_t jobject_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_jobject_t *self = self_in; mp_uint_t idx = mp_obj_get_int(index); char class_name[64]; get_jclass_name(self->obj, class_name); //printf("class: %s\n", class_name); if (class_name[0] == '[') { if (class_name[1] == 'L' || class_name[1] == '[') { if (value == MP_OBJ_NULL) { // delete assert(0); } else if (value == MP_OBJ_SENTINEL) { // load jobject el = JJ(GetObjectArrayElement, self->obj, idx); return new_jobject(el); } else { // store jvalue jval; const char *t = class_name + 1; py2jvalue(&t, value, &jval); JJ(SetObjectArrayElement, self->obj, idx, jval.l); return mp_const_none; } } mp_not_implemented(""); } if (!JJ(IsInstanceOf, self->obj, List_class)) { return MP_OBJ_NULL; } if (value == MP_OBJ_NULL) { // delete assert(0); } else if (value == MP_OBJ_SENTINEL) { // load jobject el = JJ(CallObjectMethod, self->obj, List_get_mid, idx); check_exception(); return new_jobject(el); } else { // store assert(0); } return MP_OBJ_NULL; }
STATIC void jobject_attr(mp_obj_t self_in, qstr attr_in, mp_obj_t *dest) { if (dest[0] == MP_OBJ_NULL) { // load attribute mp_obj_jobject_t *self = self_in; const char *attr = qstr_str(attr_in); jclass obj_class = JJ(GetObjectClass, self->obj); jstring field_name = JJ(NewStringUTF, attr); jobject field = JJ(CallObjectMethod, obj_class, Class_getField_mid, field_name); JJ(DeleteLocalRef, field_name); JJ(DeleteLocalRef, obj_class); if (!JJ1(ExceptionCheck)) { jfieldID field_id = JJ(FromReflectedField, field); JJ(DeleteLocalRef, field); jobject obj = JJ(GetObjectField, self->obj, field_id); dest[0] = new_jobject(obj); return; } //JJ1(ExceptionDescribe); JJ1(ExceptionClear); mp_obj_jmethod_t *o = m_new_obj(mp_obj_jmethod_t); o->base.type = &jmethod_type; o->name = attr_in; o->meth = NULL; o->obj = self->obj; o->is_static = false; dest[0] = o; } }
void tested_threads_init(int mode){ tested_thread_sturct_t *tts; jobject monitor; jrawMonitorID raw_monitor; JNIEnv * jni_env; IDATA status; int i; jni_env = jthread_get_JNI_env(jthread_self()); if (mode != TTS_INIT_DIFFERENT_MONITORS){ monitor = new_jobject(); status = jthread_monitor_init(monitor); tf_assert_same_v(status, TM_ERROR_NONE); } status = jthread_raw_monitor_create(&raw_monitor); tf_assert_same_v(status, TM_ERROR_NONE); reset_tested_thread_iterator(&tts); for (i = 0; i < MAX_TESTED_THREAD_NUMBER; i++){ tts = &tested_threads[i]; tts->my_index = i; tts->java_thread = new_jobject_thread(jni_env); tts->native_thread = NULL; tts->jvmti_start_proc_arg = &tts->jvmti_start_proc_arg; hysem_create(&tts->started, 0, 1); hysem_create(&tts->running, 0, 1); hysem_create(&tts->stop_request, 0, 1); hysem_create(&tts->ended, 0, 1); tts->phase = TT_PHASE_NONE; if (mode == TTS_INIT_DIFFERENT_MONITORS){ monitor = new_jobject(); status = jthread_monitor_init(monitor); tf_assert_same_v(status, TM_ERROR_NONE); } tts->monitor = monitor; tts->raw_monitor = raw_monitor; tts->excn = NULL; } }
STATIC void check_exception(void) { jobject exc = JJ1(ExceptionOccurred); if (exc) { //JJ1(ExceptionDescribe); mp_obj_t py_e = new_jobject(exc); JJ1(ExceptionClear); if (JJ(IsInstanceOf, exc, IndexException_class)) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_IndexError, py_e)); } nlr_raise(mp_obj_new_exception_arg1(&mp_type_Exception, py_e)); } }
// jvalue is known to be union of jobject and friends. And yet from C's // perspective, it's aggregate object which may require passing via stack // instead of registers. Work that around by passing jobject and typecasting // it. STATIC mp_obj_t jvalue2py(const char *jtypesig, jobject arg) { if (arg == NULL || MATCH(jtypesig, "void")) { return mp_const_none; } else if (MATCH(jtypesig, "boolean")) { return mp_obj_new_bool((bool)arg); } else if (MATCH(jtypesig, "int")) { return mp_obj_new_int((mp_int_t)arg); } else if (is_object_type(jtypesig)) { // Non-primitive, object type return new_jobject(arg); } printf("Unknown return type: %s\n", jtypesig); return MP_OBJ_NULL; }
STATIC mp_obj_t mod_jni_array(mp_obj_t type_in, mp_obj_t size_in) { if (!env) { create_jvm(); } mp_int_t size = mp_obj_get_int(size_in); jobject res = NULL; if (MP_OBJ_IS_TYPE(type_in, &jclass_type)) { mp_obj_jclass_t *jcls = type_in; res = JJ(NewObjectArray, size, jcls->cls, NULL); } else if (MP_OBJ_IS_STR(type_in)) { const char *type = mp_obj_str_get_str(type_in); switch (*type) { case 'Z': res = JJ(NewBooleanArray, size); break; case 'B': res = JJ(NewByteArray, size); break; case 'C': res = JJ(NewCharArray, size); break; case 'S': res = JJ(NewShortArray, size); break; case 'I': res = JJ(NewIntArray, size); break; case 'J': res = JJ(NewLongArray, size); break; case 'F': res = JJ(NewFloatArray, size); break; case 'D': res = JJ(NewDoubleArray, size); break; } } return new_jobject(res); }
STATIC mp_obj_t jobject_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_jobject_t *self = self_in; if (!JJ(IsInstanceOf, self->obj, List_class)) { return MP_OBJ_NULL; } mp_uint_t idx = mp_obj_get_int(index); if (value == MP_OBJ_NULL) { // delete assert(0); } else if (value == MP_OBJ_SENTINEL) { // load jobject el = JJ(CallObjectMethod, self->obj, List_get_mid, idx); check_exception(); return new_jobject(el); } else { // store assert(0); } return MP_OBJ_NULL; }
STATIC mp_obj_t call_method(jobject obj, const char *name, jarray methods, bool is_constr, mp_uint_t n_args, const mp_obj_t *args) { jvalue jargs[n_args]; // printf("methods=%p\n", methods); jsize num_methods = JJ(GetArrayLength, methods); for (int i = 0; i < num_methods; i++) { jobject meth = JJ(GetObjectArrayElement, methods, i); jobject name_o = JJ(CallObjectMethod, meth, Object_toString_mid); const char *decl = JJ(GetStringUTFChars, name_o, NULL); const char *arg_types = strchr(decl, '(') + 1; //const char *arg_types_end = strchr(arg_types, ')'); // printf("method[%d]=%p %s\n", i, meth, decl); const char *meth_name = NULL; const char *ret_type = NULL; if (!is_constr) { meth_name = strprev(arg_types, '.') + 1; ret_type = strprev(meth_name, ' ') - 1; ret_type = strprev(ret_type, ' ') + 1; int name_len = strlen(name); if (strncmp(name, meth_name, name_len/*arg_types - meth_name - 1*/) || meth_name[name_len] != '('/*(*/) { goto next_method; } } // printf("method[%d]=%p %s\n", i, meth, decl); // printf("!!!%s\n", arg_types); // printf("name=%p meth_name=%s\n", name, meth_name); bool found = true; for (int i = 0; i < n_args && *arg_types != ')'; i++) { if (!py2jvalue(&arg_types, args[i], &jargs[i])) { goto next_method; } if (*arg_types == ',') { arg_types++; } } if (*arg_types != ')') { goto next_method; } if (found) { // printf("found!\n"); jmethodID method_id = JJ(FromReflectedMethod, meth); jobject res; mp_obj_t ret; if (is_constr) { JJ(ReleaseStringUTFChars, name_o, decl); res = JJ(NewObjectA, obj, method_id, jargs); return new_jobject(res); } else { if (MATCH(ret_type, "void")) { JJ(CallVoidMethodA, obj, method_id, jargs); check_exception(); ret = mp_const_none; } else if (MATCH(ret_type, "int")) { jint res = JJ(CallIntMethodA, obj, method_id, jargs); check_exception(); ret = mp_obj_new_int(res); } else if (MATCH(ret_type, "boolean")) { jboolean res = JJ(CallBooleanMethodA, obj, method_id, jargs); check_exception(); ret = mp_obj_new_bool(res); } else if (is_object_type(ret_type)) { res = JJ(CallObjectMethodA, obj, method_id, jargs); check_exception(); ret = new_jobject(res); } else { JJ(ReleaseStringUTFChars, name_o, decl); nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "cannot handle return type")); } JJ(ReleaseStringUTFChars, name_o, decl); JJ(DeleteLocalRef, name_o); JJ(DeleteLocalRef, meth); return ret; } } next_method: JJ(ReleaseStringUTFChars, name_o, decl); JJ(DeleteLocalRef, name_o); JJ(DeleteLocalRef, meth); } nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "method not found")); }