/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 /* on Linux/Intel, we'll need to put FPU into double precision mode */ #if defined(__i386__) && defined(__linux__) #include #endif #ifdef _SABLEVM_VERBOSE_INSTRUCTIONS_INLINED #define _svmm_verbose_instructions_inlined(a,b,c) \ _svmf_verbose_instructions_inlined_ptr(a,b,c) void _svmf_verbose_instructions_inlined (_svmt_JNIEnv *env, _svmt_code *pc, char *name) { if (env->vm->verbose_instructions == JNI_TRUE) { _svmf_printf (env, stderr, "T%d: [verbose instructions: executing @%p %s]\n", env->thread.id, (void *) (pc - 1), name); fflush (NULL); } } void (*_svmf_verbose_instructions_inlined_ptr) (_svmt_JNIEnv *, _svmt_code *, char *); #else #define _svmm_verbose_instructions_inlined(a,b,c) #endif #ifdef _SABLEVM_INLINED_THREADED_INTERPRETER #define _svmm_fmod(x,y) _svmf_fmod_ptr(x,y) #else #define _svmm_fmod(x,y) fmod(x,y) #endif svm_static jint _svmf_is_no_count(_svmt_code *pc){ if ((pc->jint & 0x7fffffff) == pc->jint){ return 0; } else { return 1; } } /* ---------------------------------------------------------------------- _svmf_compute_aspect_code_depth ---------------------------------------------------------------------- */ svm_static jint _svmf_compute_aspect_code_depth (_svmt_JNIEnv *_env) { jint depth = 0; _svmt_stack_frame *frame = _env->stack.current_frame; /*printf("%s\n", "compute aspect code depth"); */ if (frame->has_kind_table == 1){ depth = frame->aspect_code_depth; } return depth; } /* ---------------------------------------------------------------------- _svmf_compute_aspect_propagation_kind ---------------------------------------------------------------------- */ svm_static jint _svmf_compute_aspect_propagation_kind (_svmt_JNIEnv *_env, jint caller_kind) { jint prop_kind = caller_kind; /* 1 - ADVICE_EXECUTE, 14 - INTERMETHOD, 27 - INLINE_ACCESS_METHOD * these should really all be specified as constants somewhere */ /*printf("%s\n", "compute aspect propagation kind"); */ /*printf("caller kind: %i\n", caller_kind);*/ /*printf("caller kind in env: %i\n", _env->caller_kind);*/ if ((caller_kind == 1) || (caller_kind == 14) || (caller_kind == 27)){ prop_kind = 28; /* 28 - ASPECT_CODE */ } /* 24 - AROUND_CALLBACK, 25 - AROUND_PROCEED */ else if ((caller_kind == 24) || (caller_kind == 25)){ if (_svmf_compute_aspect_code_depth(_env) > 1){ prop_kind = 28; /* 28 - ASPECT_CODE */ } else { prop_kind = 0; /* 0 - BASE_CODE or DEFAULT */ } } else if (caller_kind == -1){ prop_kind = 0; /* no -1's in dynamic counts */ } return prop_kind; } /* ---------------------------------------------------------------------- _svmf_compute_aspect_new_kind ---------------------------------------------------------------------- */ svm_static jint _svmf_compute_aspect_new_kind (_svmt_JNIEnv *_env SVM_UNUSED, jint current_kind, jint prop_kind) { jint new_kind = current_kind; /*printf("%s\n", "compute aspect new kind"); */ /* 0 - BASE_CODE or DEFAULT, 28 - ASPECT_CODE * these should really all be specified as constants somewhere */ if ((current_kind == 0) && (prop_kind == 28)){ new_kind = 28; /* 28 - ASPECT_CODE */ /*printf("new kind is 28\n");*/ } /* 0 - BASE_CODE or DEFAULT, 28 - ASPECT_CODE * 1 - ADVICE_EXECUTE, 14 - INTER_METHOD, 27 - INLINE_ACCESS_METHOD, * 24 - AROUND_CALLBACK, 25 - AROUND_PROCEED */ else if (((current_kind == 0) || (current_kind == 28)) && (!((prop_kind == 1) || (prop_kind == 14) || (prop_kind == 27) || (prop_kind == 24) || (prop_kind == 25)))){ new_kind = prop_kind; } /* 28 - ASPECT_CODE, 0 - BASE_CODE or DEFAULT */ else if ((current_kind == 28) && (prop_kind == 0)){ new_kind = 28; /* 28 - ASPECT_CODE */ } /*if (prop_kind == 28){ printf("current kind: %i\n", current_kind); printf("new kind: %i\n", new_kind); }*/ return new_kind; } /* ---------------------------------------------------------------------- _svmf_push_aspect_new_kind ---------------------------------------------------------------------- */ svm_static jint _svmf_push_aspect_new_kind (_svmt_JNIEnv *_env, jint new_kind , jint index ) { _svmt_stack_frame *frame = _env->stack.current_frame; if ((frame->has_kind_table == 1) && (frame->kind_table != NULL)){ if (index < frame->method->prepared_info.code_length) { /*if (new_kind == 28){ printf("pushing new kind: %i\n",new_kind); printf("%s %s\n", "method: ", (**(frame->method->name)).value); }*/ frame->kind_table[index].dynamic_kind = new_kind; } } return JNI_OK; } /* ---------------------------------------------------------------------- _svmf_pop_aspect_kind_stacks ---------------------------------------------------------------------- */ svm_static jint _svmf_pop_aspect_kind_stacks (_svmt_JNIEnv *_env) { _svmt_stack_frame *frame = _env->stack.current_frame; /* should really free temp here */ if ((frame->has_kind_table == 1) && (frame->kind_table != NULL)){ _svmf_free(frame->kind_table); } return JNI_OK; } /* ---------------------------------------------------------------------- _svmf_compute_aspect_current_kind ---------------------------------------------------------------------- */ svm_static jint _svmf_compute_aspect_current_kind (_svmt_JNIEnv *_env, jint index) { jint current_kind = 0; _svmt_stack_frame *frame = _env->stack.current_frame; _svmt_method_info *method = frame->method; jboolean isNative = _svmf_is_set_flag(method->access_flags, SVM_ACC_NATIVE); _svmt_stack_frame *prev_frame = frame; if (isNative){ return current_kind; } /* look through call stack for last invoke of this method * if there is one get current from there * otherwise get current from static table */ current_kind = method->prepared_info.instruction_kind_info[index].kind; /*printf("current kind: %i\n", current_kind);*/ while ((prev_frame->previous_offset > 0) && (_env->vm->alloc_count > 0)){ prev_frame = (_svmt_stack_frame *) (void *) (((char *)prev_frame) - prev_frame->previous_offset); if (prev_frame->method->method_id == frame->method->method_id) break; } if ((prev_frame != NULL) && (prev_frame->method->method_id == frame->method->method_id) && (prev_frame->has_kind_table == 1)){ current_kind = prev_frame->kind_table[index].dynamic_kind; } /*else if (method->prepared_info.instruction_kind_info != NULL){ current_kind = method->prepared_info.instruction_kind_info[index].kind; }*/ if (current_kind == -1){ /* promote to 0 - no -1's in dynamic counts */ current_kind = 0; } return current_kind; } /* ---------------------------------------------------------------------- _svmf_decr_aspect_code_depth ---------------------------------------------------------------------- */ svm_static jint _svmf_decr_aspect_code_depth (_svmt_JNIEnv *_env) { _svmt_stack_frame *frame = _env->stack.current_frame; frame->aspect_code_depth--; return JNI_OK; } /* ---------------------------------------------------------------------- _svmf_is_proceed_method ---------------------------------------------------------------------- */ svm_static jint _svmf_is_proceed_method (_svmt_JNIEnv *_env) { _svmt_stack_frame *frame = _env->stack.current_frame; _svmt_method_info *method = frame->method; jint attr_count = method->attributes_count; _svmt_attribute_info **attributes = method->attributes; jint result = 0; jint i; /*printf("%s\n", "is proceed method"); */ for (i = 0; i < attr_count; i++){ if (strcmp (DREF (attributes[i]->name, value), "ca.mcgill.sable.ProceedMethod") == 0){ result = 1; } } return result; } /* ---------------------------------------------------------------------- _svmf_incr_aspect_code_depth ---------------------------------------------------------------------- */ svm_static jint _svmf_incr_aspect_code_depth (_svmt_JNIEnv *_env) { _svmt_stack_frame *frame = _env->stack.current_frame; frame->aspect_code_depth++; return JNI_OK; } /* ---------------------------------------------------------------------- _svmf_compute_dynamic_aspect_kind ---------------------------------------------------------------------- */ svm_static jint _svmf_compute_dynamic_aspect_kind (_svmt_JNIEnv *_env , _svmt_code *pc) { jint dynamic_kind = 0; _svmt_stack_frame *frame = _env->stack.current_frame; _svmt_method_info *method = frame->method; _svmt_code *code = method->prepared_info.code; /*printf("%s%i\n", "frame has kind table: ", frame->has_kind_table); printf("%s%i\n", "pc-code: ", pc-code); printf("%s%i\n", "code_length: ", method->prepared_info.code_length);*/ if ((frame->has_kind_table == 1) && ((pc-code) >= 0) && ((pc-code) < method->prepared_info.code_length)){ dynamic_kind = frame->kind_table[pc - code].dynamic_kind; /*printf("getting dynamic kind: %i\n",dynamic_kind); printf("%s %s\n", "method: ", (**(frame->method->name)).value);*/ } return dynamic_kind; } /* ---------------------------------------------------------------------- _svmf_handle_aspect_invoke ---------------------------------------------------------------------- */ svm_static jint _svmf_handle_aspect_invoke (_svmt_JNIEnv *env) { jint caller_kind = env->caller_kind; jint prop_kind = caller_kind; jint i; jboolean isNative = JNI_FALSE; /* get current meth */ _svmt_stack_frame *frame = env->stack.current_frame; _svmt_method_info *method = frame->method; isNative = _svmf_is_set_flag(method->access_flags, SVM_ACC_NATIVE); if (isNative){ return JNI_OK; } if (method->prepared_info.code_length <=0){ return JNI_OK; } frame->kind_table = NULL; prop_kind = _svmf_compute_aspect_propagation_kind (env, caller_kind); /*printf("%s%i\n", "caller kind ", caller_kind); printf("%s%i\n", "prop kind ", prop_kind);*/ /*printf("%s %s\n", "handling aspect invoke", (**(method->name)).value);*/ /* determine whether to inc or dec aspect code depth*/ if (caller_kind == 1){ if (_svmf_incr_aspect_code_depth (env) != JNI_OK) { /*printf("error incr code depth\n");*/ return JNI_ERR; } } else if (_svmf_is_proceed_method(env) == 1){ if (_svmf_decr_aspect_code_depth (env) != JNI_OK) { /*printf("error decr code depth\n");*/ return JNI_ERR; } } /* for every pc in callee method compute current * and new kind */ frame->kind_table = _svmf_malloc (sizeof(_svmt_instruction_dynamic_kind_table) * method->prepared_info.code_length); /*printf("%s %s\n", "allocated kind table", (**(method->name)).value); printf("%s %i\n", "length of kind table", method->prepared_info.code_length);*/ env->vm->alloc_count++; /** * init table */ for (i = 0; i < method->prepared_info.code_length; i++){ frame->kind_table[i].dynamic_kind = frame->method->prepared_info.instruction_kind_info[i].kind; } frame->has_kind_table = 1; for (i = 0; i < method->prepared_info.code_length; i++){ jint current_kind; jint new_kind; current_kind = _svmf_compute_aspect_current_kind(env, i); new_kind = _svmf_compute_aspect_new_kind(env, current_kind, prop_kind); /*printf("%s%i\n", "current kind: ", current_kind); printf("%s%i\n", "new kind: ", new_kind);*/ if (_svmf_push_aspect_new_kind(env, new_kind, i) != JNI_OK){ return JNI_ERR; } } return JNI_OK; } /* ---------------------------------------------------------------------- _svmf_handle_aspect_return ---------------------------------------------------------------------- */ svm_static jint _svmf_handle_aspect_return (_svmt_JNIEnv *env) { _svmt_stack_frame *frame = env->stack.current_frame; _svmt_method_info *method = frame->method; jboolean isNative = _svmf_is_set_flag(method->access_flags, SVM_ACC_NATIVE); if (isNative){ return JNI_OK; } env->vm->alloc_count--; /* as we store the code depth in the call frame we * don't need to explicitly pop it off the stack */ if (_svmf_pop_aspect_kind_stacks(env) != JNI_OK){ return JNI_ERR; } return JNI_OK; } /* ---------------------------------------------------------------------- _svmf_aspect_counter ---------------------------------------------------------------------- */ svm_static jint _svmf_aspect_counter (_svmt_JNIEnv *_env, _svmt_code *pc) { _svmt_JavaVM *vm = _env->vm; jboolean isNative = JNI_FALSE; jboolean isApp = JNI_FALSE; jint instruction_kind = -1; jint dynamic_kind = -1; jint dynamic_kind_app_only = -1; jint instruction_source = -1; jint instruction_shadow = -1; _svmt_stack_frame *frame = _env->stack.current_frame; _svmt_method_info *method = frame->method; isNative = _svmf_is_set_flag(method->access_flags, SVM_ACC_NATIVE); _env->caller_kind = 0; /*printf("%s %i\n", "size of long" ,sizeof(long));*/ _env->vm->exec_inst++; if (method->class_info != NULL){ if (method->class_info->class_loader_info != NULL){ if (method->class_info->class_loader_info->class_loader == NULL){ _env->vm->exec_lib_inst++; } else { _env->vm->exec_app_inst++; isApp = JNI_TRUE; if (!isNative){ dynamic_kind_app_only = _svmf_compute_dynamic_aspect_kind(_env, pc); /*printf("dynamic kind executed: %i\n",dynamic_kind);*/ /*_env->caller_kind = dynamic_kind;*/ /*if (_env->caller_kind == -1){*/ /* if caller kind is -1 chnage to 0 - no -1's in dynamic algorithm */ /*_env->caller_kind = 0; }*/ /* dynamic app only counts */ if (dynamic_kind_app_only == -1){ vm->instr_dynamic_kind_app_only[36]++; _env->vm->kind_tagged_dynamic_inst_app_only++; } else { if (!_svmf_is_no_count(pc) && (dynamic_kind_app_only <= 35)){ /*printf("%s", "instruction kind: "); printf("%i\n", instruction_kind);*/ vm->instr_dynamic_kind_app_only[dynamic_kind_app_only]++; _env->vm->kind_tagged_dynamic_inst_app_only++; } } } } } } if (!isNative){ dynamic_kind = _svmf_compute_dynamic_aspect_kind(_env, pc); /*printf("dynamic kind executed: %i\n",dynamic_kind);*/ _env->caller_kind = dynamic_kind; if (_env->caller_kind == -1){ /* if caller kind is -1 chnage to 0 - no -1's in dynamic algorithm */ _env->caller_kind = 0; } /* dynamic counts */ if (dynamic_kind == -1){ vm->instr_dynamic_kind[36]++; _env->vm->kind_tagged_dynamic_inst++; } else { if (!_svmf_is_no_count(pc) && (dynamic_kind <= 35)){ /*printf("%s", "instruction kind: "); printf("%i\n", instruction_kind);*/ vm->instr_dynamic_kind[dynamic_kind]++; _env->vm->kind_tagged_dynamic_inst++; } } } if ((!isNative) && method->data.code_attribute != NULL && method->data.code_attribute->instruction_kinds != NULL && method->data.code_attribute->instruction_sources != NULL && method->data.code_attribute->instruction_shadows != NULL) { _svmt_code *code = method->prepared_info.code; _svmt_instruction_source_count_table *sources = vm->sources_counter; _svmt_instruction_shadow_count_table *shadows = vm->shadows_counter; instruction_kind = method->prepared_info.instruction_kind_info[pc - code].kind; /*dynamic_kind = _svmf_compute_dynamic_aspect_kind(_env, pc); _env->caller_kind = dynamic_kind; if (_env->caller_kind == -1){*/ /* if caller kind is -1 chnage to 0 - no -1's in dynamic algorithm */ /* _env->caller_kind = 0; }*/ /*printf("caller kind before invoke: %i\n", _env->caller_kind);*/ instruction_source = method->prepared_info.instruction_kind_info[pc - code].source; instruction_shadow = method->prepared_info.instruction_kind_info[pc - code].shadow; assert(instruction_kind <= 35); /* this part is inefficient */ while (sources != NULL){ if (sources->id == instruction_source) break; sources = sources->next; } while (shadows != NULL){ if (shadows->id == instruction_shadow) break; shadows = shadows->next; } if (sources != NULL){ if (instruction_kind == -1){ sources->instr_kind[36]++; } else { if (!_svmf_is_no_count(pc)){ sources->instr_kind[instruction_kind]++; } } } if (shadows != NULL){ if (instruction_kind == -1){ shadows->instr_kind[36]++; } else { if (!_svmf_is_no_count(pc)){ shadows->instr_kind[instruction_kind]++; } } } if (instruction_kind == -1){ vm->instr_kind[36]++; _env->vm->kind_tagged_inst++; } else { if (!_svmf_is_no_count(pc)){ /*printf("%s", "instruction kind: "); printf("%i\n", instruction_kind);*/ vm->instr_kind[instruction_kind]++; _env->vm->kind_tagged_inst++; } } /* dynamic counts */ /*if (dynamic_kind == -1){ vm->instr_dynamic_kind[36]++; _env->vm->kind_tagged_dynamic_inst++; } else { if (!_svmf_is_no_count(pc) && (dynamic_kind <= 35)){*/ /*printf("%s", "instruction kind: "); printf("%i\n", instruction_kind);*/ /*vm->instr_dynamic_kind[dynamic_kind]++; _env->vm->kind_tagged_dynamic_inst++; } }*/ } else if (isApp){ _env->vm->appNoTagCount++; } return JNI_OK; } /* ---------------------------------------------------------------------- _svmf_interpreter ---------------------------------------------------------------------- */ svm_static jint _svmf_interpreter (_svmt_JNIEnv *_env) { _svmt_JNIEnv *volatile env = _env; register _svmt_stack_value *stack = NULL; register _svmt_stack_value *locals = NULL; register _svmt_code *pc = NULL; register jint stack_size; /* exception addresses * * The idea is that normal gotos/calls might be compiled to relative * jumps, preventing their usage in inlined-threaded code. Using a * goto is an elegant way to avoid using method calls in ATHROW * (necessary to create a new null pointer exception). * [ NOTE: fatal_error_handler_ptr is currently not used because for GCC ] * [ 3.x we needed arch-specific assembly implementation of goto anyway. ] * [ But it's kept here in case it was useful with other compilers and ] * [ as a well documented and neat idea that once was implemented. ] * * A last note:We must guard against a too clever compiler that * would detect a unique value in a variable; we do this by * initializing goto address variable to NULL, and changing its * value to the correct one when initializing the instruction array. * Ahh! So many little details to get right for things to work... */ #ifdef _SABLEVM_INLINABILITY_TESTING static _svmt_code *(*no_inlining_increment_pc) (_svmt_JNIEnv *, _svmt_word, _svmt_code *) = NULL; #endif #if defined(_SABLEVM_SIGNALS_FOR_EXCEPTIONS) || defined (_SABLEVM_INLINABILITY_TESTING) sigjmp_buf *volatile previous_signal_handler = env->signal_handler; sigjmp_buf signal_handler; #endif #ifdef _SABLEVM_INLINED_THREADED_INTERPRETER /* static void *fatal_error_handler_ptr = NULL; */ double (*_svmf_fmod_ptr) (double x, double y) = &fmod; #endif #ifdef _SABLEVM_VERBOSE_INSTRUCTIONS_INLINED _svmf_verbose_instructions_inlined_ptr = &_svmf_verbose_instructions_inlined; #endif #ifdef _SABLEVM_INLINABILITY_TESTING env->inlinability_testing.sigsegv_expected = JNI_FALSE; #endif assert (*(env->throwable) == NULL); #if defined(_SABLEVM_SIGNALS_FOR_EXCEPTIONS) || defined (_SABLEVM_INLINABILITY_TESTING) /* set signal handler */ if (sigsetjmp (signal_handler, 1)) { jint signal_code = env->signal_code; #ifndef NDEBUG env->signal_code = SVM_SIGNAL_NONE; #endif switch (signal_code) { #if defined(_SABLEVM_INLINABILITY_TESTING) case SVM_SIGNAL_INLINING_FAILURE: { /* note failed bytecode test if we know which one was that */ _svmt_method_info *method = env->stack.current_frame->method; int byname = _svmf_get_bytecode_by_method_name (env, DREF (method-> name, value)); if (byname >= 0) { _svmf_printf (env, stderr, "REGISTERING failed bytecode: %s\n", env->vm->instructions[byname].name); env->inlinability_testing.bytecode_inlinability[byname] |= SVM_BCI_FAILING; } else { _svmf_printf (env, stderr, "UNABLE to find which bytecode failed!\n"); } _svmf_printf (env, stderr, "UNEXPECTED SIGNAL CAUGHT Class: %s - REVERSED BACKTRACE FOLLOWS:\n", env->stack.current_frame->method->class_info->name); _svmf_no_inlining (env, 0, SVM_IS_INLINED_GET_BACKTRACE); { /* pop stack frame */ _svmt_stack_frame *frame = env->stack.current_frame; env->stack.current_frame = (_svmt_stack_frame *) (((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; } } assert (*(env->throwable) == NULL); goto inliningexception_handler; } } break; #endif #if defined(_SABLEVM_SIGNALS_FOR_EXCEPTIONS) case SVM_SIGNAL_NULL_POINTER_EXCEPTION: { /* if initializing this vm, we store into _svmv_codes the address of the initialized static local array */ if (env->stack.current_frame == NULL) { goto initialize_instructions; } else { goto nullpointerexception_handler; } } break; #endif #if defined(_SABLEVM_SIGNALS_FOR_EXCEPTIONS) || defined (_SABLEVM_INLINABILITY_TESTING) /* Exceptionally - even in inlinability testing mode w/o signals_for_excpetions * we want this signal to be catched or else - it'd kill JVM. * Most important goal is to let the *inlinability* tests be completed. * And we'll clearly indicate that these bytecodes need to be fixed. */ case SVM_SIGNAL_ARITHMETIC_EXCEPTION: { #if (!defined(_SABLEVM_SIGNALS_FOR_EXCEPTIONS)) && defined (_SABLEVM_INLINABILITY_TESTING) /* note failed bytecode test if we know which one was that */ _svmt_method_info *method = env->stack.current_frame->method; int byname = _svmf_get_bytecode_by_method_name (env, DREF (method-> name, value)); if (byname >= 0) env->inlinability_testing.bytecode_inlinability[byname] |= SVM_BCI_SIGFPE; #endif goto arithmeticexception_handler; } break; #endif default: { #if defined (_SABLEVM_INLINABILITY_TESTING) _svmf_printf (env, stderr, "KILLER ERROR: imposible control flow; signal_code is %i\n", signal_code); fflush (NULL); goto inliningexception_handler; #endif _svmm_fatal_error ("impossible control flow"); } break; } } env->signal_handler = &signal_handler; #endif #if !defined(_SABLEVM_SIGNALS_FOR_EXCEPTIONS) if (env->stack.current_frame == NULL) { goto initialize_instructions; } #endif /* ! _SABLEVM_SIGNALS_FOR_EXCEPTIONS */ { /* When _SABLEVM_SIGNALS_FOR_EXCEPTIONS is defined, the following code causes a sigfault at the time of initialization of vm->instructions, as env->stack.current_frame is NULL at that point. The advantage of using this weird control flow on initialization is to eliminate "initialization test" overhead from normal _svmf_interpreter execution path. Not a thing you should teach cs-101 students ;-) */ _svmt_stack_frame *frame = env->stack.current_frame; _svmt_method_info *method = frame->method; locals = (_svmt_stack_value *) (void *) (((char *) frame) - method->frame_info->start_offset); 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); } /* on Linux/Intel, put FPU into double precision mode */ #if defined(__i386__) && defined(__linux__) /* This puts the X86 FPU in 64-bit precision mode as opposed to the default 80-bit mode (used by Linux). For more explanations see: http://www.srware.com/linux_numerics.txt Originally it was put into lib_init.c but apparently some code executed later resets the flag so we set it to "right" value on each interpreter invocation. TODO: find out where/what exacly resets the flag. */ { fpu_control_t fpu_control; _FPU_GETCW (fpu_control); fpu_control &= ~_FPU_EXTENDED; fpu_control |= _FPU_DOUBLE; _FPU_SETCW (fpu_control); } #endif /* i386 && linux */ #if !defined(NDEBUG) _svmf_verbose_methods_enter (env); #endif pc = env->stack.current_frame->pc; stack_size = 0; #if defined(_SABLEVM_INLINED_THREADED_INTERPRETER) || defined(_SABLEVM_DIRECT_THREADED_INTERPRETER) goto *((pc++)->implementation); #else dispatch: /*printf("%s%i\n", "pc count aspect", pc->aspect_count);*/ assert (*(env->throwable) == NULL); assert (stack_size >= 0); assert (stack_size == 0 || env->stack.current_frame->method == &env->vm->internal_call_method || env->stack.current_frame->method == &env->vm->vm_initiated_call_method || stack_size <= env->stack.current_frame->method->data.code_attribute->max_stack); _svmf_aspect_counter(env, pc); /*printf("%s%x\n", "pc: ",pc->jint); if (_svmf_is_no_count(pc)){ _svmf_unset_no_count(pc); }*/ /*printf("%s%x\n", "pc: ",pc->jint);*/ switch ((pc++)->jint & 0x7fffffff) { #include "instructions_switch.c" default: { _svmm_fatal_error ("impossible control flow"); } break; } #endif /* defined(_SABLEVM_INLINED_THREADED_INTERPRETER) || defined(_SABLEVM_DIRECT_THREADED_INTERPRETER) */ _svmm_fatal_error ("impossible control flow"); athrow_handler: if (*(env->throwable) == NULL) { goto nullpointerexception_handler; } goto exception_handler; arithmeticexception_handler: _svmf_error_ArithmeticException (env); goto exception_handler; classcastexception_handler: _svmf_error_ClassCastException (env); goto exception_handler; nullpointerexception_handler: _svmf_error_NullPointerException (env); goto exception_handler; #if defined(_SABLEVM_INLINABILITY_TESTING) inliningexception_handler: _svmf_error_InliningException (env); goto exception_handler; #endif arrayindexoutofboundsexception_handler: _svmf_error_ArrayIndexOutOfBoundsException (env); goto exception_handler; arraystoreexception_handler: _svmf_error_ArrayStoreException (env); goto exception_handler; abstractmethoderror_handler: _svmf_error_AbstractMethodError (env); goto exception_handler; exception_handler: assert (*(env->throwable) != NULL); #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->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_info *method = frame->method; exception_loop: pc = frame->pc; 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); #if defined(_SABLEVM_SIGNALS_FOR_EXCEPTIONS) || defined (_SABLEVM_INLINABILITY_TESTING) env->signal_handler = previous_signal_handler; #endif 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 ((pc >= table[i].normal_start && pc <= table[i].normal_end) || (pc >= table[i].prepare_start && pc <= table[i].prepare_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->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); } /* 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))) { locals = (_svmt_stack_value *) (void *) (((char *) frame) - method->frame_info->start_offset); stack = (_svmt_stack_value *) (void *) (((char *) frame) + _svmv_stack_offset); pc = table[i].handler; stack_size = 1; stack[0].reference = *(env->throwable); *(env->throwable) = NULL; #if defined(_SABLEVM_INLINED_THREADED_INTERPRETER) || defined(_SABLEVM_DIRECT_THREADED_INTERPRETER) goto *((pc++)->implementation); #else goto dispatch; #endif } } } /* structured locking */ if (env->stack.current_frame->lock_count != 0) { /* 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; method = frame->method; goto exception_loop; } _svmm_fatal_error ("impossible control flow"); #ifdef COMMENT #ifdef _SABLEVM_INLINED_THREADED_INTERPRETER fatal_error_handler: _svmm_fatal_error ("impossible control flow"); return JNI_ERR; #endif #endif /* COMMENT */ initialize_instructions: { jint instr; for (instr = 0; instr < SVM_INSTRUCTION_COUNT; instr++) { switch (instr) { #ifdef _SABLEVM_INLINED_THREADED_INTERPRETER #include "instructions_preparation_inlined_threaded.c" #endif #ifdef _SABLEVM_DIRECT_THREADED_INTERPRETER #include "instructions_preparation_direct_threaded.c" #endif #ifdef _SABLEVM_SWITCH_THREADED_INTERPRETER #include "instructions_preparation_switch_threaded.c" #endif case SVM_INSTRUCTION_UNDEFINED_186: { _svmm_zero_memory (env->vm->instructions[instr]); } break; default: { _svmm_fatal_error ("impossible control flow"); } break; } } /* initialize goto/call addresses */ #ifdef _SABLEVM_INLINED_THREADED_INTERPRETER /* fatal_error_handler_ptr = &&fatal_error_handler; */ if (!_svmv_true) { /* we have to play this trick to assure this won't get optimized somewhere under way */ _svmf_fmod_ptr = NULL; #ifdef _SABLEVM_VERBOSE_INSTRUCTIONS_INLINED _svmf_verbose_instructions_inlined_ptr = NULL; #endif } #endif #ifdef _SABLEVM_INLINABILITY_TESTING no_inlining_increment_pc = &_svmf_no_inlining_increment_pc; #endif #if defined(_SABLEVM_SIGNALS_FOR_EXCEPTIONS) || defined(_SABLEVM_INLINABILITY_TESTING) env->signal_handler = previous_signal_handler; #endif /* _SABLEVM_SIGNALS_FOR_EXCEPTIONS || _SABLEVM_INLINABILITY_TESTING */ return JNI_OK; } }