/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* ---------------------------------------------------------------------- _svmm_identity_hashcode ---------------------------------------------------------------------- */ #define _svmm_identity_hashcode(env, obj, hashcode) \ _svmh_identity_hashcode (env, obj, &hashcode) svm_static jint _svmh_identity_hashcode (_svmt_JNIEnv *env, jobject obj, jint *phashcode) { _svmt_JavaVM *vm = env->vm; jboolean monitor_acquired = JNI_FALSE; /* is it an array? */ if (_svmf_lockword_is_array ((*obj)->lockword)) { assert (!monitor_acquired); *phashcode = (*(_svmf_cast_jarray (obj)))->hashcode; return JNI_OK; } retry: { _svmt_object_instance *instance = *obj; _svmt_word state = _svmf_lockword_get_hashstate (instance->lockword); switch (state) { case SVM_HASH_NONE: { /*** BUG BUG BUG ***/ /* The untold story in the 2 bits hashcode within a thin lock is that it cannot be modified unless a) the current thread owns the lock, or b) no thread owns it! In the following code, we lock the object. If the lock succeeds, either the lock was free, or it was owned by the current thread. If the lock was owned by another thread, then the current thread waits for it to be freed... BUG! (because of possible deadlock) To solve the bug: We need a non-blocking enter_monitor function. We also need a list of native references to "hash-accessed" objects. When locking fails, the hashcode is computed, and the object is added to this list. Or maybe: Alternatively, we could suspend the owning thread, then it would be safe to play with the lockword bits. This solution leaves GC unchanged, unlike the previous solution. */ if (!monitor_acquired) { /* Possible deadlock. See above! */ if (_svmf_enter_object_monitor (env, *obj)) { return JNI_ERR; } monitor_acquired = JNI_TRUE; goto retry; } #if defined (_SABLEVM_COPY_GC) || defined (_SABLEVM_GENCOPY_GC) /* we must make sure there will be enough space to store the hashcode at gc time */ { jint end_of_heap, status = JNI_OK; _svmm_mutex_lock (vm->global_mutex); /* remember that allocation is made in multiples of SVM_ALIGNMENT */ if (vm->heap.alloc == vm->heap.end) end_of_heap = JNI_TRUE; else end_of_heap = JNI_FALSE; if (end_of_heap == JNI_TRUE) { #if defined (_SABLEVM_COPY_GC) status = _svmf_copy_gc_no_exception (env, SVM_ALIGNMENT); #elif defined (_SABLEVM_GENCOPY_GC) status = _svmf_gencopy_gc_no_exception (env, SVM_ALIGNMENT); #endif } if ((end_of_heap == JNI_FALSE) || (status == JNI_OK)) { #if defined (_SABLEVM_GENCOPY_GC) if (_svmf_in_nursery (env, *obj)) vm->heap.hashed_notmoved_nursery++; #endif vm->heap.hashed_notmoved++; vm->heap.end = ((char *) vm->heap.end) - SVM_ALIGNMENT; } _svmm_mutex_unlock (); if (status != JNI_OK) { if (_svmf_exit_object_monitor (env, *obj) != JNI_OK) { return JNI_ERR; } _svmf_error_OutOfMemoryError (env); return JNI_ERR; } /* in case gc moved things around */ instance = *obj; } #endif _svmm_lockword_set_hashstate (instance->lockword, SVM_HASH_NOT_MOVED); #if defined (_SABLEVM_NO_GC) || defined (_SABLEVM_COPY_GC) *phashcode = vm->heap.hashcode_base + (size_t) instance; #elif defined (_SABLEVM_GENCOPY_GC) if (_svmf_in_nursery (env, instance)) *phashcode = vm->heap.hashcode_base_nursery + (size_t) instance; else *phashcode = vm->heap.hashcode_base - (size_t) instance; #else #error todo #endif } break; case SVM_HASH_NOT_MOVED: { #if defined (_SABLEVM_NO_GC) || defined (_SABLEVM_COPY_GC) *phashcode = vm->heap.hashcode_base + (size_t) instance; #elif defined (_SABLEVM_GENCOPY_GC) if (_svmf_in_nursery (env, instance)) *phashcode = vm->heap.hashcode_base_nursery + (size_t) instance; else *phashcode = vm->heap.hashcode_base - (size_t) instance; #else #error todo #endif } break; case SVM_HASH_MOVED: { *phashcode = _svmf_get_INT_field (instance, instance->vtable->hashcode_offset); } break; default: { _svmm_fatal_error ("impossible control flow"); } break; } } if (monitor_acquired) { monitor_acquired = JNI_FALSE; if (_svmf_exit_object_monitor (env, *obj) != JNI_OK) { return JNI_ERR; } } return JNI_OK; } /* ---------------------------------------------------------------------- _svmf_is_assignable_from ---------------------------------------------------------------------- */ inline svm_static jboolean _svmf_is_assignable_from (_svmt_JNIEnv *env, _svmt_type_info *from, _svmt_type_info *to) { _svmt_JavaVM *vm = env->vm; _svmt_type_info *S = from; _svmt_type_info *T = to; #ifndef _SABLEVM_INLINED_THREADED_INTERPRETER assert (S != NULL); assert (T != NULL); #endif loop: if (!(S->is_array)) { _svmt_class_info *cS = _svmf_cast_class (S); if (!_svmf_is_set_flag (cS->access_flags, SVM_ACC_INTERFACE)) { /* S is a class */ if (!(T->is_array)) { _svmt_class_info *cT = _svmf_cast_class (T); if (!_svmf_is_set_flag (cT->access_flags, SVM_ACC_INTERFACE)) { /* T is a class */ jint s = cS->data.noninterface.super_classes_size; jint t = cT->data.noninterface.super_classes_size; if ((s < t) || (cS->data.noninterface.super_classes[t - 1] != cT)) { return JNI_FALSE; } else { return JNI_TRUE; } } else { /* T is an interface */ jint s = cS->data.noninterface.max_interface_id; jint t = cT->data.interface.interface_id; if ((s < t) || (_svmf_get_bit (cS->data.noninterface.super_interfaces, t) == 0)) { return JNI_FALSE; } else { return JNI_TRUE; } } } else { /* T is an array */ return JNI_FALSE; } } else { /* S is an interface */ if (!(T->is_array)) { _svmt_class_info *cT = _svmf_cast_class (T); if (!_svmf_is_set_flag (cT->access_flags, SVM_ACC_INTERFACE)) { /* T is a class */ if (cT == vm->class_loading.boot_loader.classes.jlobject) { return JNI_TRUE; } else { return JNI_FALSE; } } else { /* T is an interface */ jint s = cS->data.interface.interface_id; jint t = cT->data.interface.interface_id; if ((s < t) || (_svmf_get_bit (cS->data.interface.super_interfaces, t) == 0)) { return JNI_FALSE; } else { return JNI_TRUE; } } } else { /* T is an array */ return JNI_FALSE; } } } else { /* S is an array */ _svmt_array_info *aS = _svmf_cast_array (S); if (!(T->is_array)) { _svmt_class_info *cT = _svmf_cast_class (T); if (!_svmf_is_set_flag (cT->access_flags, SVM_ACC_INTERFACE)) { /* T is a class */ if (cT == vm->class_loading.boot_loader.classes.jlobject) { return JNI_TRUE; } else { return JNI_FALSE; } } else { /* T is an interface */ if ((cT == vm->class_loading.boot_loader.classes.jlcloneable) || (cT == vm->class_loading.boot_loader.classes.jiserializable)) { return JNI_TRUE; } else { return JNI_FALSE; } } } else { /* T is an array */ _svmt_array_info *aT = _svmf_cast_array (T); if ((aS->dimensions == 1 && aS->base_type != SVM_TYPE_REFERENCE) || (aT->dimensions == 1 && aT->base_type != SVM_TYPE_REFERENCE)) { /* S or T is an array of primitive type */ if (aS->dimensions == aT->dimensions && aS->base_type == aT->base_type) { return JNI_TRUE; } else { return JNI_FALSE; } } /* redo with element types */ if (aS->dimensions == 1) { #ifndef _SABLEVM_INLINED_THREADED_INTERPRETER assert (aS->base_type == SVM_TYPE_REFERENCE); assert (aS->base_class != NULL); #endif S = _svmf_cast_type_class (aS->base_class); } else { #ifndef _SABLEVM_INLINED_THREADED_INTERPRETER assert (aS->array_element != NULL); #endif S = _svmf_cast_type_array (aS->array_element); } if (aT->dimensions == 1) { #ifndef _SABLEVM_INLINED_THREADED_INTERPRETER assert (aT->base_type == SVM_TYPE_REFERENCE); assert (aT->base_class != NULL); #endif T = _svmf_cast_type_class (aT->base_class); } else { #ifndef _SABLEVM_INLINED_THREADED_INTERPRETER assert (aT->array_element != NULL); #endif T = _svmf_cast_type_array (aT->array_element); } goto loop; } } #ifndef _SABLEVM_INLINED_THREADED_INTERPRETER _svmm_fatal_error ("impossible control flow"); #endif } /* ---------------------------------------------------------------------- _svmf_set_reference_array_element_no_exception ---------------------------------------------------------------------- */ inline svm_static jint _svmf_set_reference_array_element_no_exception (_svmt_JNIEnv *env, _svmt_array_instance *array, jint indx, _svmt_object_instance *value) { _svmt_object_instance **elements; #ifndef _SABLEVM_INLINED_THREADED_INTERPRETER assert (array != NULL); assert (array->vtable->type->is_array); assert (indx >= 0 && indx < array->size); assert (array->vtable->type->is_array == JNI_TRUE); #endif /* check that value is of appropriate type */ if (value != NULL) { _svmt_array_info *array_type = _svmf_cast_array (array->vtable->type); _svmt_type_info *element_type; if (array_type->dimensions > 1) { #ifndef _SABLEVM_INLINED_THREADED_INTERPRETER assert (array_type->array_element != NULL); #endif element_type = _svmf_cast_type_array (array_type->array_element); } else { #ifndef _SABLEVM_INLINED_THREADED_INTERPRETER assert (array_type->dimensions == 1); assert (array_type->base_type == SVM_TYPE_REFERENCE); assert (array_type->base_class != NULL); #endif element_type = _svmf_cast_type_class (array_type->base_class); } if (!_svmf_is_assignable_from (env, value->vtable->type, element_type)) { return JNI_ERR; } } #if defined (_SABLEVM_BIDIRECTIONAL_OBJECT_LAYOUT) elements = (_svmt_object_instance **) array; elements[(-1) - indx] = value; #if defined (_SABLEVM_GC_WRITE_BARRIER) _svmf_write_barrier (env, (_svmt_object_instance **) &elements[(-1) - indx]); #endif /* _SABLEVM_GC_WRITE_BARRIER */ #else elements = (_svmt_object_instance **) (((char *) array) + _svmf_aligned_size_t (sizeof (_svmt_array_instance))); elements[indx] = value; #if defined (_SABLEVM_GC_WRITE_BARRIER) _svmf_write_barrier (env, (_svmt_object_instance **) &elements[indx]); #endif /* _SABLEVM_GC_WRITE_BARRIER */ #endif return JNI_OK; } /* ---------------------------------------------------------------------- _svmf_tree_compare_type ---------------------------------------------------------------------- */ inline svm_static jint _svmf_tree_compare_type (_svmt_type_node *value1, _svmt_type_node *value2) { assert (value1 != NULL); assert (value2 != NULL); return strcmp (value1->name, value2->name); } /* ---------------------------------------------------------------------- _svmf_tree_compare_interface_method_signature ---------------------------------------------------------------------- */ inline svm_static jint _svmf_tree_compare_imethod_signature (_svmt_imethod_signature_node *value1, _svmt_imethod_signature_node *value2) { jint diff = strcmp (value1->name, value2->name); if (diff == 0) { diff = strcmp (value1->descriptor, value2->descriptor); } return diff; } /* ---------------------------------------------------------------------- _svmf_tree_compare_gc_map ---------------------------------------------------------------------- */ inline svm_static jint _svmf_tree_compare_gc_map (_svmt_gc_map_node *value1, _svmt_gc_map_node *value2) { jint diff; jint i; jint size; assert (value1 != NULL); assert (value2 != NULL); diff = value1->size - value2->size; i = 0; size = value1->size; while (diff == 0 && i < size) { diff = _svmf_get_bit (value1->bits, i) - _svmf_get_bit (value2->bits, i); i++; } return diff; } /* ---------------------------------------------------------------------- _svmf_tree_compare_sequence ---------------------------------------------------------------------- */ inline svm_static jint _svmf_tree_compare_sequence (_svmt_sequence_node *value1, _svmt_sequence_node *value2) { jint diff; jint i; jint size; assert (value1 != NULL); assert (value2 != NULL); diff = value1->instructions_length - value2->instructions_length; i = 0; size = value1->instructions_length; while (diff == 0 && i < size) { diff = value1->instructions[i] - value2->instructions[i]; i++; } return diff; } /* ---------------------------------------------------------------------- _svmf_tree_compare_internal_method ---------------------------------------------------------------------- */ inline svm_static jint _svmf_tree_compare_internal_method (_svmt_internal_method_node *value1, _svmt_internal_method_node *value2) { assert (value1 != NULL); assert (value2 != NULL); return strcmp (value1->name, value2->name); } /* ---------------------------------------------------------------------- _svmh_global_copy_jobject ---------------------------------------------------------------------- */ inline svm_static jint _svmh_global_copy_jobject (_svmt_JNIEnv *env, jobject src, jobject *dest) { assert (src != NULL); if (_svmm_new_native_global (env, *dest) != JNI_OK) { return JNI_ERR; } **dest = *src; return JNI_OK; } /* ---------------------------------------------------------------------- _svmh_galloc_copy_str_no_exception ---------------------------------------------------------------------- */ #define _svmm_galloc_copy_str_no_exception(dst, src) \ _svmh_galloc_copy_str_no_exception (&dst, src) svm_static jint _svmh_galloc_copy_str_no_exception (char **dest, const char *src) { char *tmp; assert (src != NULL); tmp = _svmf_malloc (strlen (src) + 1); if (tmp == NULL) { return JNI_ERR; } strcpy (tmp, src); *dest = tmp; return JNI_OK; } /* ---------------------------------------------------------------------- _svmh_gfree_str_no_exception ---------------------------------------------------------------------- */ #define _svmm_gfree_str_no_exception(str) \ _svmh_gfree_str_no_exception (&str) svm_static void _svmh_gfree_str_no_exception (char **str) { assert (*str != NULL); _svmf_free (*str); *str = NULL; } /* ---------------------------------------------------------------------- _svmh_galloc_copy_str ---------------------------------------------------------------------- */ #define _svmm_galloc_copy_str(env, dst, src) \ _svmh_galloc_copy_str (env, &dst, src) svm_static jint _svmh_galloc_copy_str (_svmt_JNIEnv *env, char **dest, const char *src) { char *tmp; assert (src != NULL); tmp = _svmf_malloc (strlen (src) + 1); if (tmp == NULL) { _svmf_error_OutOfMemoryError (env); return JNI_ERR; } strcpy (tmp, src); *dest = tmp; return JNI_OK; } /* ---------------------------------------------------------------------- _svmh_gfree_str ---------------------------------------------------------------------- */ #define _svmm_gfree_str(str) \ _svmh_gfree_str (&str) svm_static void _svmh_gfree_str (char **str) { assert (*str != NULL); _svmf_free (*str); *str = NULL; } /* ---------------------------------------------------------------------- _svmh_new_native_global_array ---------------------------------------------------------------------- */ #ifdef COMMENT static jint _svmh_new_native_global_array (_svmt_JNIEnv *env, jarray *array) { return _svmh_new_native_global (env, (jobject *) array); } #endif /* COMMENT */ /* ---------------------------------------------------------------------- _svmh_free_native_global_array ---------------------------------------------------------------------- */ #ifdef COMMENT static void _svmh_free_native_global_array (_svmt_JNIEnv *env, jarray *pglobal_arrayref) { _svmh_free_native_global (env, (jobject *) pglobal_arrayref); } #endif /* COMMENT */ /* ---------------------------------------------------------------------- _svmh_new_native_local_array ---------------------------------------------------------------------- */ static jint _svmh_new_native_local_array (_svmt_JNIEnv *env, jarray *array) { return _svmh_new_native_local (env, (jobject *) array); } /* ---------------------------------------------------------------------- _svmh_free_native_local_array ---------------------------------------------------------------------- */ static void _svmh_free_native_local_array (_svmt_JNIEnv *env, jarray *pglobal_arrayref) { _svmh_free_native_local (env, (jobject *) pglobal_arrayref); } /* ---------------------------------------------------------------------- _svmh_local_wrap_pointer ---------------------------------------------------------------------- */ svm_static jint _svmh_local_wrap_pointer (_svmt_JNIEnv *env, void *pointer, jbyteArray *pwrapper) { _svmt_JavaVM *vm = env->vm; jbyteArray wrapper = NULL; if (_svmm_new_native_local_array (env, wrapper) != JNI_OK) { return JNI_ERR; } if (_svmm_new_array_instance (env, vm->class_loading.boot_loader.classes.byte_array, sizeof (void *), *wrapper) != JNI_OK) { _svmm_free_native_local_array (env, wrapper); return JNI_ERR; } /* put "pointer" into the "wrapper" array */ *((void **) (void *) (((char *) *wrapper) + _svmf_aligned_size_t (sizeof (_svmt_array_instance)))) = pointer; *pwrapper = wrapper; return JNI_OK; } /* ---------------------------------------------------------------------- _svmf_wrap_pointer ---------------------------------------------------------------------- */ svm_static jint _svmf_wrap_pointer (_svmt_JNIEnv *env, void *pointer, jbyteArray wrapper) { _svmt_JavaVM *vm = env->vm; if (_svmm_new_array_instance (env, vm->class_loading.boot_loader.classes.byte_array, sizeof (void *), *wrapper) != JNI_OK) { return JNI_ERR; } /* put "pointer" into the "wrapper" array */ *((void **) (void *) (((char *) *wrapper) + _svmf_aligned_size_t (sizeof (_svmt_array_instance)))) = pointer; return JNI_OK; } /* ---------------------------------------------------------------------- _svmf_unwrap_pointer ---------------------------------------------------------------------- */ static void * _svmf_unwrap_pointer (_svmt_array_instance *wrapper) { return *((void **) (void *) (((char *) wrapper) + _svmf_aligned_size_t (sizeof (_svmt_array_instance)))); } /* ---------------------------------------------------------------------- _svmf_unwrap_class_instance ---------------------------------------------------------------------- */ svm_static _svmt_type_info * _svmf_unwrap_class_instance (_svmt_JNIEnv *env, jclass class) { _svmt_JavaVM *vm = env->vm; _svmt_array_instance *vmdata; vmdata = _svmf_cast_array_instance (_svmf_get_REFERENCE_field (*class, vm->class_loading.boot_loader.fields. jlclass_vmdata->data.instance_field.offset)); return (_svmt_type_info *) _svmf_unwrap_pointer (vmdata); } /* ---------------------------------------------------------------------- _svmf_unwrap_field_instance ---------------------------------------------------------------------- */ svm_static _svmt_field_info * _svmf_unwrap_field_instance (_svmt_JNIEnv *env, jobject obj) { _svmt_JavaVM *vm = env->vm; _svmt_array_instance *vmdata; vmdata = _svmf_cast_array_instance (_svmf_get_REFERENCE_field (*obj, vm->class_loading.boot_loader.fields. jlrfield_vmdata->data.instance_field.offset)); return (_svmt_field_info *) _svmf_unwrap_pointer (vmdata); } /* ---------------------------------------------------------------------- _svmf_unwrap_method_instance ---------------------------------------------------------------------- */ svm_static _svmt_method_info * _svmf_unwrap_method_instance (_svmt_JNIEnv *env, jobject obj) { _svmt_JavaVM *vm = env->vm; _svmt_array_instance *vmdata; vmdata = _svmf_cast_array_instance (_svmf_get_REFERENCE_field (*obj, vm->class_loading.boot_loader.fields. jlrmethod_vmdata->data.instance_field. offset)); return (_svmt_method_info *) _svmf_unwrap_pointer (vmdata); } /* ---------------------------------------------------------------------- _svmf_new_class ---------------------------------------------------------------------- */ svm_static jint _svmf_new_class_pd (_svmt_JNIEnv *env, _svmt_type_info *type, jobject protection_domain) { _svmt_JavaVM *vm = env->vm; jbyteArray data = NULL; jclass class_instance = NULL; if (_svmm_local_wrap_pointer (env, type, data) != JNI_OK) { return JNI_ERR; } if (_svmm_new_native_global (env, class_instance) != JNI_OK) { _svmm_free_native_local_array (env, data); return JNI_ERR; } if (_svmm_new_object_instance (env, vm->class_loading.boot_loader.classes.jlclass, *class_instance) != JNI_OK) { _svmm_free_native_local_array (env, data); _svmm_free_native_global (env, class_instance); return JNI_ERR; } if (_svmm_invoke_nonvirtual_jlclass_init (env, class_instance, _svmf_cast_jobject (data), protection_domain) != JNI_OK) { _svmm_free_native_local_array (env, data); _svmm_free_native_global (env, class_instance); return JNI_ERR; } _svmm_free_native_local_array (env, data); type->class_instance = class_instance; return JNI_OK; } svm_static jint _svmf_new_class (_svmt_JNIEnv *env, _svmt_type_info *type) { return _svmf_new_class_pd (env, type, (jobject) (NULL)); } /* ---------------------------------------------------------------------- _svmf_find_method_in_class ---------------------------------------------------------------------- */ /* inline static _svmt_method_info * _svmf_find_method_in_class (_svmt_class_info *class, const char *name, const char *descriptor) { jint methods_count = class->methods_count; _svmt_method_info *methods = class->methods; jint i; for (i = 0; i < methods_count; i++) { _svmt_method_info *method = &methods[i]; if (strcmp (name, DREF (method->name, value)) == 0 && strcmp (descriptor, DREF (method->descriptor, value)) == 0) { return method; } } return NULL; } */ /* ---------------------------------------------------------------------- _svmf_get_string ---------------------------------------------------------------------- */ svm_static jint _svmf_get_string (_svmt_JNIEnv *env, const char *value, jstring str) { _svmt_JavaVM *vm = env->vm; jbyteArray data = NULL; jint length = strlen (value); jint status; if (_svmm_new_native_local_array (env, data) != JNI_OK) { return JNI_ERR; } if (_svmm_new_array_instance (env, vm->class_loading.boot_loader.classes.byte_array, length, *data) != JNI_OK) { _svmm_free_native_local_array (env, data); return JNI_ERR; } /* put the string characters into the "wrapper" array without including the end-of-string '\0' marker */ strncpy (((char *) *data) + _svmf_aligned_size_t (sizeof (_svmt_array_instance)), value, length); status = _svmm_invoke_static_stringcreator_createstring (env, _svmf_cast_jobject (data), str); _svmm_free_native_local_array (env, data); return status; } /* ---------------------------------------------------------------------- _svmf_get_interned_string ---------------------------------------------------------------------- */ svm_static jint _svmf_get_interned_string (_svmt_JNIEnv *env, const char *value, jstring str) { _svmt_JavaVM *vm = env->vm; jbyteArray data = NULL; jint length = strlen (value); jint status; if (_svmm_new_native_local_array (env, data) != JNI_OK) { return JNI_ERR; } if (_svmm_new_array_instance (env, vm->class_loading.boot_loader.classes.byte_array, length, *data) != JNI_OK) { _svmm_free_native_local_array (env, data); return JNI_ERR; } /* put the string characters into the "wrapper" array without including the end-of-string '\0' marker */ strncpy (((char *) *data) + _svmf_aligned_size_t (sizeof (_svmt_array_instance)), value, length); status = _svmm_invoke_static_stringcreator_createinternedstring (env, _svmf_cast_jobject (data), str); _svmm_free_native_local_array (env, data); return status; } /* ---------------------------------------------------------------------- _svmf_get_current_working_directory ---------------------------------------------------------------------- */ svm_static const char * _svmf_get_current_working_directory (void) { size_t size = 1024; char *buffer = _svmf_malloc (size); while (buffer != NULL) { if (getcwd (buffer, size) != NULL) { return buffer; } _svmf_free (buffer); { size_t old_size = size; size *= 2; if (size <= old_size) { return NULL; } } buffer = _svmf_malloc (size); } return NULL; } /* ---------------------------------------------------------------------- _svmm_galloc_utf_chars ---------------------------------------------------------------------- */ #define _svmm_galloc_utf_chars(env, src, dst) \ _svmh_galloc_utf_chars (env, src, &dst) #define _svmm_gfree_utf_chars(str) \ _svmm_gfree_str(str) svm_static jint _svmh_galloc_utf_chars (_svmt_JNIEnv *env, jstring src, char **pdst) { jbyteArray bytes; char *result; if (_svmm_new_native_local_array (env, bytes) != JNI_OK) { return JNI_ERR; } if (_svmm_invoke_static_stringcreator_getutfchars (env, src, _svmf_cast_jobject (bytes)) != JNI_OK) { _svmm_free_native_local_array (env, bytes); return JNI_ERR; } { char *str = ((char *) *bytes) + _svmf_aligned_size_t (sizeof (_svmt_array_instance)); if (_svmm_galloc_copy_str (env, result, str) != JNI_OK) { _svmm_free_native_local_array (env, bytes); return JNI_ERR; } _svmm_free_native_local_array (env, bytes); *pdst = result; return JNI_OK; } } /* ---------------------------------------------------------------------- _svmf_is_super_class ---------------------------------------------------------------------- */ svm_static jboolean _svmf_is_super_class (_svmt_class_info *class1, _svmt_class_info *class2) { _svmt_class_info *current; if (CAN_DREF (class2->super_class)) { current = _svmf_cast_class (DREF (class2->super_class, type)); } else { current = NULL; } while (current != NULL) { if (current == class1) { return JNI_TRUE; } if (CAN_DREF (current->super_class)) { current = _svmf_cast_class (DREF (current->super_class, type)); } else { current = NULL; } } return JNI_FALSE; } /* ---------------------------------------------------------------------- _svmf_get_current_class_loader ---------------------------------------------------------------------- */ svm_static _svmt_class_loader_info * _svmf_get_current_class_loader (_svmt_JNIEnv *env) { _svmt_JavaVM *vm = env->vm; _svmt_stack_frame *frame = env->stack.current_frame; _svmt_method_info *method = frame->method; while (method != &vm->stack_bottom_method && method != &vm->vm_initiated_call_method) { if ((!_svmf_is_set_flag (method->access_flags, SVM_ACC_INTERNAL)) && method->class_info->class_loader_info->class_loader != NULL) { return method->class_info->class_loader_info; } frame = (_svmt_stack_frame *) (void *) (((char *) frame) - frame->previous_offset); method = frame->method; } return vm->class_loading.boot_loader.class_loader_info; } /* ---------------------------------------------------------------------- _svmf_enter_class_loader_monitor ---------------------------------------------------------------------- */ svm_static jint _svmf_enter_class_loader_monitor (_svmt_JNIEnv *env, _svmt_class_loader_info *class_loader_info) { if (class_loader_info->class_loader == NULL) { _svmt_JavaVM *vm = env->vm; assert (class_loader_info == vm->class_loading.boot_loader.class_loader_info); if (_svmf_enter_object_monitor (env, *(vm->class_loading.boot_loader.classes.virtualmachine-> class_instance)) != JNI_OK) { return JNI_ERR; } } else { if (_svmf_enter_object_monitor (env, *(class_loader_info->class_loader)) != JNI_OK) { return JNI_ERR; } } return JNI_OK; } /* ---------------------------------------------------------------------- _svmf_exit_class_loader_monitor ---------------------------------------------------------------------- */ svm_static jint _svmf_exit_class_loader_monitor (_svmt_JNIEnv *env, _svmt_class_loader_info *class_loader_info) { if (class_loader_info->class_loader == NULL) { _svmt_JavaVM *vm = env->vm; assert (class_loader_info == vm->class_loading.boot_loader.class_loader_info); if (_svmf_exit_object_monitor (env, *(vm->class_loading.boot_loader.classes.virtualmachine-> class_instance)) != JNI_OK) { return JNI_ERR; } } else { if (_svmf_exit_object_monitor (env, *(class_loader_info->class_loader)) != JNI_OK) { return JNI_ERR; } } return JNI_OK; } /* ---------------------------------------------------------------------- _svmf_wrap_exception_in_invocationte ---------------------------------------------------------------------- */ /* This function wraps the "current_exception" parameter into a new InvocationTargetException instance, then throws it. */ svm_static int _svmf_wrap_exception_in_invocationte (_svmt_JNIEnv *env, jobject current_exception) { _svmt_JavaVM *vm = env->vm; jobject invocationte = NULL; jint status; if (_svmm_new_native_local (env, invocationte) != JNI_OK) { return JNI_ERR; } if (_svmm_new_object_instance (env, vm->class_loading.boot_loader.classes.jlrinvocationtargetexception, *invocationte) != JNI_OK) { _svmm_free_native_local (env, invocationte); return JNI_ERR; } status = _svmm_invoke_nonvirtual_jlrinvocationtargetexception_init (env, invocationte, current_exception); /* if no exception was raised, throw InvocationTargetException instance */ if (status == JNI_OK) { *(env->throwable) = *invocationte; } _svmm_free_native_local (env, invocationte); return JNI_ERR; } /* ---------------------------------------------------------------------- _svmf_verbose_methods_enter (_svmt_JNIEnv *env) ---------------------------------------------------------------------- */ #ifndef NDEBUG inline svm_static void _svmf_verbose_methods_enter (_svmt_JNIEnv *env) { if (env->vm->verbose_methods == JNI_TRUE) { _svmt_method_info *method = env->stack.current_frame->method; _svmf_printf (env, stderr, "T%d: [verbose methods: entering method %s.%s%s]\n", env->thread.id, method->class_info->name, DREF (method->name, value), DREF (method->descriptor, value)); } } #endif /* !NDEBUG */ /* ---------------------------------------------------------------------- _svmf_verbose_methods_exit (_svmt_JNIEnv *env) ---------------------------------------------------------------------- */ #ifndef NDEBUG inline svm_static void _svmf_verbose_methods_exit (_svmt_JNIEnv *env) { if (env->vm->verbose_methods == JNI_TRUE) { _svmt_method_info *method = env->stack.current_frame->method; _svmf_printf (env, stderr, "T%d: [verbose methods: exiting method %s.%s%s]\n", env->thread.id, method->class_info->name, DREF (method->name, value), DREF (method->descriptor, value)); { _svmt_method_info *caller_method; _svmt_stack_frame *caller_frame = env->stack.current_frame; caller_frame = (_svmt_stack_frame *) (void *) (((char *) caller_frame) - caller_frame->previous_offset); caller_method = caller_frame->method; while (_svmf_is_set_flag (caller_method->access_flags, SVM_ACC_INTERNAL) && caller_method != &env->vm->stack_bottom_method) { caller_frame = (_svmt_stack_frame *) (void *) (((char *) caller_frame) - caller_frame->previous_offset); caller_method = caller_frame->method; } if (!_svmf_is_set_flag (caller_method->access_flags, SVM_ACC_INTERNAL)) { _svmf_printf (env, stderr, "T%d: [ returning to %s.%s%s]\n", env->thread.id, caller_method->class_info->name, DREF (caller_method->name, value), DREF (caller_method->descriptor, value)); } } } } #endif /* !NDEBUG */ /* ---------------------------------------------------------------------- _svmf_print_statistics ---------------------------------------------------------------------- */ #ifdef STATISTICS svm_static void _svmf_print_statistics (_svmt_JNIEnv *env) { _svmt_JavaVM *vm = env->vm; _svmf_printf (env, stderr, "\nSTATS: Number of prepared classes: %d\n", vm->class_count); _svmf_printf (env, stderr, "STATS: Number of prepared interfaces: %d\n", vm->interface_count); _svmf_printf (env, stderr, "STATS: Number of prepared arrays: %d\n", vm->array_count); _svmf_printf (env, stderr, "STATS: Number of prepared methods: %d\n", vm->method_count); _svmf_printf (env, stderr, "STATS: Number of prepared bytecode instructions: %d\n", vm->bytecode_instruction_count); _svmf_printf (env, stderr, "STATS: Number of prepared bytecodes: %d\n", vm->bytecode_count); _svmf_printf (env, stderr, "STATS: Code array size: %d\n\n", vm->code_size); _svmf_printf (env, stderr, "STATS: Maximum stack size: %d\n", vm->max_stack_size); _svmf_printf (env, stderr, "STATS: Number of locals on stack: %d\n", vm->stack_local_count); _svmf_printf (env, stderr, "STATS: Number of split locals on stack: %d\n\n", vm->stack_local_split_count); _svmf_printf (env, stderr, "STATS: Total sparse interface virtual tables size: %d\n", vm->total_ivtables); _svmf_printf (env, stderr, "STATS: Total interface virtual table holes size: %d\n", vm->total_holes); _svmf_printf (env, stderr, "STATS: Total wasted holes size: %d\n\n", vm->total_lost_holes); _svmf_printf (env, stderr, "STATS: Total GC maps size: %d\n", vm->total_gc_maps_size); _svmf_printf (env, stderr, "STATS: GC maps count: %d\n", vm->total_gc_maps_count); _svmf_printf (env, stderr, "STATS: GC points count: %d\n\n", vm->check_points_count); _svmf_printf (env, stderr, "STATS: Original locals count: %d\n", vm->total_orig_locals_count); _svmf_printf (env, stderr, "STATS: Unused locals count: %d\n", vm->total_unused_locals_count); _svmf_printf (env, stderr, "STATS: Added locals count: %d\n\n", vm->total_added_locals_count); #if defined (_SABLEVM_INLINED_THREADED_INTERPRETER) _svmf_printf (env, stderr, "STATS: Number of distinct (inlined) threads:: %d\n", vm->distinct_inlined_threads_count); _svmf_printf (env, stderr, "STATS: Total bytecode count of distinct threads: %d\n", vm->total_distinct_thread_bc_length); _svmf_printf (env, stderr, "STATS: Total inlined size of distinct threads: %d\n\n", vm->total_distinct_thread_inlined_length); _svmf_printf (env, stderr, "STATS: Number of (inlined) threads:: %d\n", vm->inlined_threads_count); _svmf_printf (env, stderr, "STATS: Total bytecode count of threads: %d\n", vm->total_thread_bc_length); _svmf_printf (env, stderr, "STATS: Total inlined size of threads: %d\n\n", vm->total_thread_inlined_length); _svmf_printf (env, stderr, "STATS: Maximum thread bytecode count: %d\n", vm->max_thread_bc_length); _svmf_printf (env, stderr, "STATS: Maximum thread inlined size: %d\n\n", vm->max_thread_inlined_length); #endif } #endif /* STATISTICS */