/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* ---------------------------------------------------------------------- _svmh_new_native_local ---------------------------------------------------------------------- */ static jint _svmh_new_native_local (_svmt_JNIEnv *env, jobject *pobj) { _svmt_JavaVM *vm = env->vm; _svmt_native_ref *native_local = NULL; /* do we already have a free reference available? */ if (env->native_locals.free_list != NULL) { native_local = env->native_locals.free_list; env->native_locals.free_list = native_local->next; if (env->native_locals.free_list != NULL) { assert (env->native_locals.free_list->previous == native_local); env->native_locals.free_list->previous = NULL; } assert (native_local->previous == NULL); native_local->next = env->native_locals.list; env->native_locals.list = native_local; if (native_local->next != NULL) { assert (native_local->next->previous == NULL); native_local->next->previous = native_local; } *pobj = _svmf_cast_jobject_nref (native_local); return JNI_OK; } /* Can we steal a free global native reference? */ _svmm_mutex_lock (vm->global_mutex); if (vm->native_globals.free_list != NULL) { native_local = vm->native_globals.free_list; vm->native_globals.free_list = native_local->next; if (vm->native_globals.free_list != NULL) { assert (vm->native_globals.free_list->previous == native_local); vm->native_globals.free_list->previous = NULL; } } _svmm_mutex_unlock (); if (native_local != NULL) { assert (native_local->previous == NULL); native_local->next = env->native_locals.list; env->native_locals.list = native_local; if (native_local->next != NULL) { assert (native_local->next->previous == NULL); native_local->next->previous = native_local; } *pobj = _svmf_cast_jobject_nref (native_local); return JNI_OK; } /* we're out of luck; let's allocate a new reference */ if (_svmm_gzalloc_native_ref_no_exception (native_local) != JNI_OK) { _svmf_error_OutOfMemoryError (env); return JNI_ERR; } native_local->next = env->native_locals.list; env->native_locals.list = native_local; if (native_local->next != NULL) { assert (native_local->next->previous == NULL); native_local->next->previous = native_local; } *pobj = _svmf_cast_jobject_nref (native_local); return JNI_OK; } /* ---------------------------------------------------------------------- _svmh_free_native_local ---------------------------------------------------------------------- */ static void _svmh_free_native_local (_svmt_JNIEnv *env, jobject *pobj) { _svmt_native_ref *native_local = _svmf_cast_nref_jobject (*pobj); if (native_local->next != NULL) { native_local->next->previous = native_local->previous; } if (native_local->previous != NULL) { native_local->previous->next = native_local->next; } else { env->native_locals.list = native_local->next; } native_local->ref = NULL; native_local->previous = NULL; native_local->next = env->native_locals.free_list; env->native_locals.free_list = native_local; if (native_local->next != NULL) { assert (native_local->next->previous == NULL); native_local->next->previous = native_local; } *pobj = NULL; } /* ---------------------------------------------------------------------- _svmf_get_jni_frame_native_local ---------------------------------------------------------------------- */ /* NOTE: IT IS IMPORTANT to assign a value OTHER THAN NULL into the * returned jobject BEFORE calling this method again. IF YOU DON'T * follow rigorously this rule, you will probably experience problems, * as this function will repeatedly return the exact same jobject. * * This function is provided as a convenient way to avoid checking * return values (as would be necessary with _svmf_new_native_local), * by using stack frame reserved JNI jobjects. Its primary function * is to help implement the JNI mechanism. So, if you're not sure, * simply use _svmf_new_native_local; you'll then be safe. */ static jobject _svmf_get_jni_frame_native_local (_svmt_JNIEnv *env) { _svmt_JavaVM *vm = env->vm; _svmt_stack_frame *frame = env->stack.current_frame; _svmt_method_info *method = frame->method; _svmt_stack_native_reference *lrefs = (_svmt_stack_native_reference *) (((char *) frame) + frame->end_offset); jint lrefs_count = lrefs[-1].jint; size_t lrefs_size = lrefs[-2].size_t; jint i; assert (method == &vm->stack_bottom_method || _svmf_is_set_flag (method->access_flags, SVM_ACC_NATIVE)); lrefs = (_svmt_stack_native_reference *) (((char *) lrefs) - lrefs_size); for (i = 0; i < lrefs_count; i++) { if (*(lrefs[i].jobject) == NULL) { return lrefs[i].jobject; } } _svmf_jni_fatal_error ("Local reference capacity exceeded"); return NULL; /* to keep compiler happy. */ } /* ---------------------------------------------------------------------- _svmm_release_jni_frame_native_local ---------------------------------------------------------------------- */ #define _svmm_release_jni_frame_native_local(obj) \ _svmh_release_jni_frame_native_local (&obj) static void _svmh_release_jni_frame_native_local (jobject *pobj) { **pobj = NULL; *pobj = NULL; } /* ---------------------------------------------------------------------- _svmf_get_jni_frame_native_local_array ---------------------------------------------------------------------- */ /* NOTE: IT IS IMPORTANT to assign a value OTHER THAN NULL into the * returned jarray BEFORE calling this method again. IF YOU DON'T * follow rigorously this rule, you will probably experience problems, * as this function will repeatedly return the exact same jarray. * * This function is provided as a convenient way to avoid checking * return values (as would be necessary with * _svmf_new_native_local_array), by using stack frame reserved JNI * jobjects. Its primary function is to help implement the JNI * mechanism. So, if you're not sure, simply use * _svmf_new_native_local_array; you'll then be safe. */ static jarray _svmf_get_jni_frame_native_local_array (_svmt_JNIEnv *env) { return _svmf_cast_jarray (_svmf_get_jni_frame_native_local (env)); } /* ---------------------------------------------------------------------- _svmm_release_jni_frame_native_local_array ---------------------------------------------------------------------- */ #define _svmm_release_jni_frame_native_local_array(array) \ _svmh_release_jni_frame_native_local_array (&array) static void _svmh_release_jni_frame_native_local_array (jarray *parray) { **parray = NULL; *parray = NULL; }