/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This file is part of SableVM. * * See the file "LICENSE" for Copyright information and the * * terms and conditions for copying, distribution and * * modification of SableVM. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* ---------------------------------------------------------------------- Java_java_lang_reflect_Method_invokeNative ---------------------------------------------------------------------- */ /* * Class: java_lang_reflect_Method * Method: invokeNative * Signature: ([B[CCLjava/lang/Object;[Ljava/lang/Object;Ljava/lang/Object;)V */ JNIEXPORT void JNICALL Java_java_lang_reflect_Method_invokeNative (JNIEnv *_env, jclass _class, jbyteArray vmData, jcharArray _params, jchar resultType, jobject obj, jobjectArray _args, jobject result) { _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env); _svmf_resuming_java (env); { _svmt_method_info *method = _svmf_unwrap_pointer (*vmData); _svmt_JavaVM *vm = env->vm; _svmt_stack_frame *initial_frame; _svmt_method_frame_info *frame_info = method->frame_info; jboolean is_static = _svmf_is_set_flag (method->access_flags, SVM_ACC_STATIC); if (!is_static) { if (obj == NULL) { _svmf_error_NullPointerException (env); goto end; } if (!_svmf_is_set_flag (method->access_flags, SVM_ACC_PRIVATE)) { /* It's not a private or static method. Dynamic lookup required. */ size_t method_offset; if (_svmf_is_set_flag (method->class_info->access_flags, SVM_ACC_INTERFACE)) { /* INVOKEINTERFACE */ method_offset = -((1 + method->method_id) * sizeof (_svmt_method_info *)); } else { /* INVOKEVIRTUAL */ method_offset = sizeof (_svmt_vtable) + (method->method_id * sizeof (_svmt_method_info *)); } /* replace "method" by appropriate call target. */ method = *((_svmt_method_info **) (((char *) (*obj)->vtable) + method_offset)); frame_info = method->frame_info; } } /* make sure the method's class is initialized */ if (_svmf_link_class (env, method->class_info) != JNI_OK) { goto end; } if (_svmf_class_initialization (env, method->class_info) != JNI_OK) { goto end; } /* syncronized? */ if (method->synchronized) { if (is_static) { if (_svmf_enter_object_monitor (env, *(method->class_info->class_instance)) != JNI_OK) { goto end; } } else { if (_svmf_enter_object_monitor (env, *obj) != JNI_OK) { goto end; } } } if (_svmf_ensure_stack_capacity (env, frame_info->internal_invoke_frame_size) != JNI_OK) { goto end; } initial_frame = env->stack.current_frame; /* setup internal call frame */ { size_t offset = env->stack.current_frame->end_offset; _svmt_stack_frame *frame = (_svmt_stack_frame *) (((char *) env->stack.current_frame) + offset); frame->previous_offset = offset; frame->end_offset = _svmf_aligned_size_t (sizeof (_svmt_stack_frame)); frame->method = &vm->internal_call_method; frame->stack_trace_element = NULL; frame->lock_count = 0; frame->this = NULL; frame->pc = vm->internal_call_method.frame_info->code; frame->stack_size = 0; env->stack.current_frame = frame; } /* push parameters */ { _svmt_stack_frame *prev_frame = env->stack.current_frame; _svmt_stack_value *locals = (_svmt_stack_value *) (((char *) prev_frame) + prev_frame->end_offset); jint i = 0; if (!is_static) { locals[i++].reference = *obj; } { _svmt_array_instance *params = *_params; _svmt_array_instance *args = *_args; jint count = params->size; jint j; for (j = 0; j < count; j++) { switch (_svmf_get_char_array_element (params, j)) { case 'Z': { _svmt_array_instance *wrapper = _svmf_cast_array_instance (_svmf_get_reference_array_element (args, j)); locals[i++].jint = _svmf_get_boolean_array_element (wrapper, 0); } break; case 'B': { _svmt_array_instance *wrapper = _svmf_cast_array_instance (_svmf_get_reference_array_element (args, j)); locals[i++].jint = _svmf_get_byte_array_element (wrapper, 0); } break; case 'S': { _svmt_array_instance *wrapper = _svmf_cast_array_instance (_svmf_get_reference_array_element (args, j)); locals[i++].jint = _svmf_get_short_array_element (wrapper, 0); } break; case 'C': { _svmt_array_instance *wrapper = _svmf_cast_array_instance (_svmf_get_reference_array_element (args, j)); locals[i++].jint = _svmf_get_char_array_element (wrapper, 0); } break; case 'I': { _svmt_array_instance *wrapper = _svmf_cast_array_instance (_svmf_get_reference_array_element (args, j)); locals[i++].jint = _svmf_get_int_array_element (wrapper, 0); } break; case 'J': { _svmt_array_instance *wrapper = _svmf_cast_array_instance (_svmf_get_reference_array_element (args, j)); *((jlong *) &locals[i]) = _svmf_get_long_array_element (wrapper, 0); i += 2; } break; case 'F': { _svmt_array_instance *wrapper = _svmf_cast_array_instance (_svmf_get_reference_array_element (args, j)); locals[i++].jfloat = _svmf_get_float_array_element (wrapper, 0); } break; case 'D': { _svmt_array_instance *wrapper = _svmf_cast_array_instance (_svmf_get_reference_array_element (args, j)); *((jdouble *) &locals[i]) = _svmf_get_double_array_element (wrapper, 0); i += 2; } break; case 'L': { locals[i++].reference = _svmf_get_reference_array_element (args, j); } break; default: { _svmm_fatal_error ("impossible control flow"); } break; } } } { jint ref_count = frame_info->non_parameter_ref_locals_count; jint j; for (j = 0; j < ref_count; j++) { locals[i++].reference = NULL; } } } /* setup java call frame */ { size_t offset = env->stack.current_frame->end_offset + frame_info->start_offset; _svmt_stack_frame *frame = (_svmt_stack_frame *) (((char *) env->stack.current_frame) + offset); frame->previous_offset = offset; frame->end_offset = frame_info->end_offset; frame->method = method; frame->stack_trace_element = NULL; frame->lock_count = 0; if (is_static) { frame->this = *(method->class_info->class_instance); } else { frame->this = *obj; } frame->pc = frame_info->code; frame->stack_size = 0; env->stack.current_frame = frame; } /* interpret and pop internal call frame */ { /* call the interpreter */ jint status = _svmf_interpreter (env); /* retrieve stack frame */ _svmt_stack_frame *frame = env->stack.current_frame; assert (frame->method == &vm->internal_call_method); /* pop frame */ env->stack.current_frame = (_svmt_stack_frame *) (((char *) frame) - frame->previous_offset); /* rethrow exception */ if (status != JNI_OK) { goto end; } /* set the return value */ { _svmt_stack_value *ptr_ret = (_svmt_stack_value *) (((char *) frame) + frame->end_offset); switch (resultType) { case 'Z': { _svmt_array_instance *wrapper = _svmf_cast_array_instance (*result); _svmf_set_boolean_array_element (wrapper, 0, ptr_ret->jint); } break; case 'B': { _svmt_array_instance *wrapper = _svmf_cast_array_instance (*result); _svmf_set_byte_array_element (wrapper, 0, ptr_ret->jint); } break; case 'S': { _svmt_array_instance *wrapper = _svmf_cast_array_instance (*result); _svmf_set_short_array_element (wrapper, 0, ptr_ret->jint); } break; case 'C': { _svmt_array_instance *wrapper = _svmf_cast_array_instance (*result); _svmf_set_char_array_element (wrapper, 0, ptr_ret->jint); } break; case 'I': { _svmt_array_instance *wrapper = _svmf_cast_array_instance (*result); _svmf_set_int_array_element (wrapper, 0, ptr_ret->jint); } break; case 'J': { _svmt_array_instance *wrapper = _svmf_cast_array_instance (*result); _svmf_set_long_array_element (wrapper, 0, *((jlong *) ptr_ret)); } break; case 'F': { _svmt_array_instance *wrapper = _svmf_cast_array_instance (*result); _svmf_set_float_array_element (wrapper, 0, ptr_ret->jfloat); } break; case 'D': { _svmt_array_instance *wrapper = _svmf_cast_array_instance (*result); _svmf_set_double_array_element (wrapper, 0, *((jdouble *) ptr_ret)); } break; case 'L': { _svmt_array_instance *wrapper = _svmf_cast_array_instance (*result); _svmf_set_reference_array_element_no_exception (env, wrapper, 0, ptr_ret-> reference); } break; case 'V': { /* do nothing */ } break; default: { _svmm_fatal_error ("impossible control flow"); } break; } } } goto end; } end: _svmf_stopping_java (env); } /* ---------------------------------------------------------------------- Java_java_lang_reflect_Method_nativeGetDescriptor ---------------------------------------------------------------------- */ /* * Class: java_lang_reflect_Method * Method: nativeGetDescriptor * Signature: ([B)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_java_lang_reflect_Method_nativeGetDescriptor (JNIEnv *_env, jclass _class, jbyteArray vmData) { _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env); jstring descriptor; _svmf_resuming_java (env); { _svmt_method_info *method = _svmf_unwrap_pointer (*vmData); descriptor = _svmf_get_jni_frame_native_local (env); _svmf_get_string (env, DREF (method->descriptor, value), descriptor); } _svmf_stopping_java (env); return descriptor; }