/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* ---------------------------------------------------------------------- _svmf_stack_init_defaults ---------------------------------------------------------------------- */ svm_static void _svmf_stack_init_defaults (_svmt_JavaVM *vm) { vm->stack_min_size = SVM_STACK_DEFAULT_MIN_SIZE; vm->stack_max_size = SVM_STACK_DEFAULT_MAX_SIZE; vm->stack_allocation_increment = SVM_STACK_DEFAULT_ALLOCATION_INCREMENT; } /* ---------------------------------------------------------------------- _svmf_stack_init ---------------------------------------------------------------------- */ svm_static jint _svmf_stack_init (_svmt_JNIEnv *env) { _svmt_JavaVM *vm = env->vm; size_t lrefs_offset = _svmf_aligned_size_t (sizeof (_svmt_stack_frame)); jint lrefs_count = SVM_FRAME_NATIVE_REFS_MIN; size_t lrefs_size = _svmf_aligned_size_t ((lrefs_count + 2) * sizeof (_svmt_stack_native_reference)); size_t frame_size = lrefs_offset + lrefs_size; size_t alloc_size; if (frame_size <= vm->stack_min_size) { alloc_size = vm->stack_min_size; } else if (vm->stack_max_size == 0 || frame_size <= vm->stack_max_size) { alloc_size = vm->stack_min_size + _svmf_aligned_to_increment (frame_size - vm->stack_min_size, vm->stack_allocation_increment); } else { _svmf_error_OutOfMemoryError (env); return JNI_ERR; } env->stack.start = _svmm_malloc (alloc_size); if (env->stack.start == NULL) { _svmf_error_OutOfMemoryError (env); return JNI_ERR; } env->stack.current_frame = env->stack.start; env->stack.end = ((char *) env->stack.start) + alloc_size; env->stack.current_frame->previous_offset = 0; env->stack.current_frame->end_offset = frame_size; env->stack.current_frame->method_frame_info = vm->stack_bottom_method.frame_info; env->stack.current_frame->stack_trace_element = NULL; env->stack.current_frame->lock_count = 0; env->stack.current_frame->this = NULL; env->stack.current_frame->pc = vm->stack_bottom_method.frame_info->code; env->stack.current_frame->stack_size = 0; { _svmt_stack_native_reference *lrefs = (_svmt_stack_native_reference *) (void *) (((char *) env->stack. current_frame) + env->stack.current_frame-> end_offset); jint i; lrefs[-1].jint = lrefs_count; lrefs[-2].size_t = lrefs_size; lrefs = (_svmt_stack_native_reference *) (void *) (((char *) lrefs) - lrefs_size); for (i = 0; i < lrefs_count; i++) { if (_svmm_new_native_local (env, lrefs[i].jobject) != JNI_OK) { return JNI_ERR; } } } return JNI_OK; } /* ---------------------------------------------------------------------- _svmf_ensure_stack_capacity ---------------------------------------------------------------------- */ svm_static jint _svmf_ensure_stack_capacity (_svmt_JNIEnv *env, size_t frame_size) { void *current_frame = env->stack.current_frame; void *current_frame_end = ((char *) current_frame) + env->stack.current_frame->end_offset; void *stack_end = env->stack.end; size_t available = ((char *) stack_end) - ((char *) current_frame_end); assert (stack_end >= current_frame_end); #ifdef STATISTICS { _svmt_JavaVM *vm = env->vm; void *stack_start = env->stack.start; _svmt_stack_frame *frame = (_svmt_stack_frame *) current_frame; size_t current_stack_size = ((char *) frame) - ((char *) stack_start); if (current_stack_size > vm->max_stack_size) { _svmt_method_info *method = env->stack.current_frame->method_frame_info->method; vm->max_stack_size = current_stack_size; vm->stack_local_count = 0; vm->stack_local_split_count = 0; while (method != &vm->stack_bottom_method) { if (!_svmf_is_set_flag (method->access_flags, SVM_ACC_INTERNAL)) { vm->stack_local_count += method->frame_info->local_count; vm->stack_local_split_count += method->frame_info->local_split_count; } frame = (_svmt_stack_frame *) (((char *) frame) - frame->previous_offset); method = frame->method_frame_info->method; } } } #endif if (frame_size > available) { _svmt_JavaVM *vm = env->vm; size_t stack_increment = vm->stack_allocation_increment; if (stack_increment == 0) { _svmf_error_OutOfMemoryError (env); return JNI_ERR; } else { size_t min_growth = frame_size - available; void *stack_start = env->stack.start; size_t current_frame_offset = ((char *) current_frame) - ((char *) stack_start); /* growth sould be a multiple of stack_increment large enough to hold min_growth */ size_t growth = _svmf_aligned_to_increment (min_growth, stack_increment); size_t current_size = ((char *) stack_end) - ((char *) stack_start); size_t new_size = current_size + growth; void *new_stack; /* detect overflows */ if ((vm->stack_max_size != 0 && new_size > vm->stack_max_size) || new_size <= current_size) { _svmf_error_OutOfMemoryError (env); return JNI_ERR; } new_stack = _svmm_realloc (stack_start, new_size); /* out of memory */ if (new_stack == NULL) { _svmf_error_OutOfMemoryError (env); return JNI_ERR; } env->stack.start = new_stack; env->stack.end = ((char *) new_stack) + new_size; env->stack.current_frame = (_svmt_stack_frame *) (void *) (((char *) new_stack) + current_frame_offset); } } return JNI_OK; }