/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This source file is part of SableVM. * * * * See the file "LICENSE" for the copyright information and for * * the terms and conditions for copying, distribution and * * modification of this source file. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include /* ---------------------------------------------------------------------- _svmf_prepare_instruction ---------------------------------------------------------------------- */ svm_static inline void _svmf_prepare_instruction (_svmt_JNIEnv *env, jint instr, jint param_count, const char *name) { env->vm->instructions[instr].code.jint = instr; env->vm->instructions[instr].param_count = param_count; #ifndef NDEBUG strcpy (env->vm->instructions[instr].name, name); #endif } /* ---------------------------------------------------------------------- _svmf_instructions_initialization ---------------------------------------------------------------------- */ svm_static void _svmf_instructions_initialization (_svmt_JNIEnv *env) { jint instr; for (instr = 0; instr < SVM_INSTRUCTION_COUNT; instr++) { switch (instr) { #include "instructions_preparation_cases.c" case SVM_INSTRUCTION_UNDEFINED_186: { _svmm_zero_memory (env->vm->instructions[instr]); } break; default: { _svmm_fatal_error ("impossible control flow"); } break; } } } /* ---------------------------------------------------------------------- _svmf_interpreter ---------------------------------------------------------------------- */ svm_static jint _svmf_interpreter (_svmt_JNIEnv *_env) { _svmt_JNIEnv *volatile env = _env; assert (*(env->throwable) == NULL); if (env->stack.current_frame == NULL) { _svmf_instructions_initialization(env); return JNI_OK; } { _svmt_stack_frame *frame = env->stack.current_frame; _svmt_method_frame_info *frame_info = frame->method_frame_info; env->stack.current_frame->locals = (_svmt_stack_value *) (void *) (((char *) frame) - frame_info->start_offset); env->stack.current_frame->stack = (_svmt_stack_value *) (void *) (((char *) frame) + _svmv_stack_offset); assert (env->stack.current_frame->this != NULL); assert (env->stack.current_frame->stack_size == 0); /* check */ _svmf_periodic_check (env); } /* Asssure that FPU is in 64-bit precision mode */ _svmf_set_fpu_double_precision_mode(); #if !defined(NDEBUG) _svmf_verbose_methods_enter (env); #endif env->stack.current_frame->stack_size = 0; dispatch: assert (*(env->throwable) == NULL); assert (env->stack.current_frame->stack_size >= 0); assert (env->stack.current_frame->stack_size == 0 || env->stack.current_frame->method_frame_info->method == &env->vm->internal_call_method || env->stack.current_frame->method_frame_info->method == &env->vm->vm_initiated_call_method || env->stack.current_frame->stack_size <= env->stack.current_frame->method_frame_info->method->data. code_attribute->max_stack); switch ((env->stack.current_frame->pc++)->jint) { #include "instructions_switch_cases.c" default: { _svmm_fatal_error ("impossible control flow"); } break; } _svmm_fatal_error ("impossible control flow"); exception_handler: assert (*(env->throwable) != NULL); assert (_svmf_is_assignable_from (env, (*(env->throwable))->vtable->type, _svmf_cast_type_class (env->vm->class_loading.boot_loader.classes. jlthrowable))); #if !defined(NDEBUG) /* dump stack trace on exception */ if (env->vm->verbose_exceptions) { _svmf_printf (env, stderr, "** thrown on thread %d: instance of type %s\n", env->vm_thread.id, (*(env->throwable))->vtable->type->name); _svmf_dump_stack_trace (env); } #endif #ifdef COMMENT if (strcmp ((*(env->throwable))->vtable->type->name, "java/lang/ClassNotFoundException") != 0 && strcmp ((*(env->throwable))->vtable->type->name, "java/lang/NoClassDefFoundError") != 0) { _svmf_printf (env, stderr, "** (on thread %d) exception: %s\n", env->thread.id, (*(env->throwable))->vtable->type->name); _svmf_dump_stack_trace (env); } #endif { jint i; jint table_length; _svmt_exception_table *table; _svmt_stack_frame *frame = env->stack.current_frame; _svmt_method_frame_info *frame_info = frame->method_frame_info; _svmt_method_info *method = frame_info->method; exception_loop: frame->stack_size = 0; if (_svmf_is_set_flag (method->access_flags, SVM_ACC_INTERNAL)) { assert (method == &env->vm->internal_call_method || method == &env->vm->vm_initiated_call_method); return JNI_ERR; } assert (!_svmf_is_set_flag (method->access_flags, SVM_ACC_NATIVE)); table_length = method->data.code_attribute->exception_table_length; table = method->data.code_attribute->exception_table; for (i = 0; i < table_length; i++) { if (frame->pc >= table[i].normal_start && frame->pc <= table[i].normal_end) { /* resolve and link type, if necessary */ if (CAN_DREF (table[i].catch_type)) { jobject pending_throwable; if (_svmm_new_native_local (env, pending_throwable) != JNI_OK) { /* to avoid infinite loops! */ goto pop_stack_frame; } /* save throwable aside, so that we can run Java code (i.e. java/lang/Class.) if necessary */ *pending_throwable = *(env->throwable); *(env->throwable) = NULL; if (_svmf_resolve_CONSTANT_Class (env, env->stack.current_frame->method_frame_info->method-> class_info, *(table[i].catch_type)) != JNI_OK) { _svmm_free_native_local (env, pending_throwable); goto pop_stack_frame; } if (_svmf_link_type (env, DREF (table[i].catch_type, type)) != JNI_OK) { _svmm_free_native_local (env, pending_throwable); goto pop_stack_frame; } /* restore pending throwable */ *(env->throwable) = *pending_throwable; _svmm_free_native_local (env, pending_throwable); frame = env->stack.current_frame; assert (method == frame->method_frame_info->method); } /* if "any" (null) or matching type */ if (CANNOT_DREF (table[i].catch_type) || _svmf_is_assignable_from (env, (*(env->throwable))->vtable->type, DREF (table[i].catch_type, type))) { frame->locals = (_svmt_stack_value *) (void *) (((char *) frame) - frame_info->start_offset); frame->stack = (_svmt_stack_value *) (void *) (((char *) frame) + _svmv_stack_offset); frame->pc = table[i].handler; frame->stack_size = 1; frame->stack[0].reference = *(env->throwable); *(env->throwable) = NULL; goto dispatch; } } } /* structured locking */ if (env->stack.current_frame->lock_count != 0 && env->vm->enforce_structured_locking) { /* pop stack frame */ frame = env->stack.current_frame; env->stack.current_frame = (_svmt_stack_frame *) (void *) (((char *) frame) - frame->previous_offset); _svmf_error_IllegalMonitorStateException (env); goto exception_handler; } #if !defined(NDEBUG) _svmf_verbose_methods_exit (env); #endif pop_stack_frame: /* pop stack frame */ frame = env->stack.current_frame; env->stack.current_frame = (_svmt_stack_frame *) (void *) (((char *) frame) - frame->previous_offset); /* is method synchronized? */ if (method->synchronized) { /* release monitor */ if (_svmf_exit_object_monitor (env, frame->this) != JNI_OK) { goto exception_handler; } } frame = env->stack.current_frame; frame_info = frame->method_frame_info; method = frame_info->method; goto exception_loop; } _svmm_fatal_error ("impossible control flow"); return JNI_ERR; }