/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #if defined (_SABLEVM_HC_COPYING) #define SVM_DEFAULT_MIN_SIZE 4194304 * 7 #define SVM_DEFAULT_MAX_SIZE 4194304 * 100 /* ---------------------------------------------------------------------- _svmf_do_copy_object ---------------------------------------------------------------------- */ inline svm_static _svmt_object_instance * _svmf_do_copy_object (_svmt_object_instance *obj, size_t start_offset, size_t requested_size, size_t instance_size, void **pto_space) { _svmt_object_instance *new_obj; memcpy (*pto_space, (void *) (((char *) obj) - start_offset), instance_size); new_obj = (_svmt_object_instance *) (((char *) *pto_space) + start_offset); *pto_space = ((char *) *pto_space) + requested_size; #if defined (MAGIC) obj->magic[0] = 0; #endif /* (MAGIC) */ /* Set forward reference. */ *((_svmt_object_instance **) obj) = new_obj; return new_obj; } /* -------------------------------------------------------------------------------- _svmf_collect_garbage -------------------------------------------------------------------------------- */ inline svm_static jint _svmf_collect_garbage (_svmt_JNIEnv *env) { _svmt_heap *heap = &(env->vm->heap); size_t to_space_size = heap->size + heap->increment_size; #if defined (_SABLEVM_HC_STATISTICS) struct timeval start_time; struct timeval end_time; long secs; long usecs; gettimeofday (&start_time, NULL); #endif /* (_SABLEVM_HC_STATISTICS) */ _svmm_mutex_lock (env->vm->global_mutex); _svmf_halt_if_requested (env); if ((heap->to_space.start = _svmm_malloc (to_space_size)) == NULL) { return JNI_ERR; } heap->to_space.end = ((char *) heap->to_space.start) + to_space_size; heap->alloc = heap->to_space; heap->size = to_space_size; /* Begin GC. */ _svmf_stop_the_world (env); pthread_mutex_unlock (&env->vm->global_mutex); _svmf_trace_roots (env); _svmf_trace_heap (env); pthread_mutex_lock (&env->vm->global_mutex); _svmf_resume_the_world (env); /* End GC. */ heap->hashcode_base += ((char *) heap->alloc.start) - ((char *) heap->to_space.start); _svmm_free (heap->space.start); heap->space = heap->to_space; _svmm_mutex_unlock (); #if defined (_SABLEVM_HC_STATISTICS) heap->gc_collections++; gettimeofday (&end_time, NULL); secs = end_time.tv_sec - start_time.tv_sec; usecs = end_time.tv_usec - start_time.tv_usec; if (usecs < 0) { usecs += 1000000; secs -= 1; } heap->gc_total_secs += secs; heap->gc_total_usecs += usecs; if (heap->gc_total_usecs > 999999) { heap->gc_total_usecs -= 1000000; heap->gc_total_secs += 1; } #endif /* (_SABLEVM_HC_STATISTICS) */ return JNI_OK; } /* ---------------------------------------------------------------------- _svmf_copy_object ---------------------------------------------------------------------- */ inline svm_static _svmt_object_instance * _svmf_copy_object (_svmt_JNIEnv *env, _svmt_object_instance *obj) { _svmt_heap *heap = &(env->vm->heap); _svmt_word lockword; if (obj == NULL) { return NULL; } assert (((void *) obj) >= heap->space.start && ((void *) obj) < heap->space.end); lockword = obj->lockword; /* Lockword is a forward reference. */ if (_svmf_lockword_is_forward_reference (lockword)) { assert (((void *) lockword) < heap->alloc.start); assert (obj->vtable == ((_svmt_object_instance *) lockword)->vtable); return (_svmt_object_instance *) lockword; } #if defined (MAGIC) assert (strcmp (obj->magic, "SableVM") == 0); #endif /* (MAGIC) */ { size_t end_offset = _svmf_get_end_offset (obj); size_t start_offset = _svmf_get_start_offset (obj); size_t instance_size = start_offset + end_offset; #if defined (_SABLEVM_HC_STATISTICS) heap->gc_bytes_copied += instance_size; heap->gc_objects_copied++; #endif /* (_SABLEVM_HC_STATISTICS) */ if (_svmf_lockword_is_array (obj->lockword)) { return _svmf_do_copy_object (obj, start_offset, instance_size, instance_size, &(heap->alloc.start)); } else { switch (_svmf_lockword_get_hashstate (obj->lockword)) { case SVM_HASH_NONE: { } case SVM_HASH_MOVED: { return _svmf_do_copy_object (obj, start_offset, instance_size, instance_size, &(heap->alloc.start)); } break; case SVM_HASH_NOT_MOVED: { _svmt_object_instance *new_obj; new_obj = _svmf_do_copy_object (obj, start_offset, instance_size + SVM_ALIGNMENT, instance_size, &(heap->alloc.start)); if (new_obj != NULL) { _svmm_lockword_set_hashstate (new_obj->lockword, SVM_HASH_MOVED); _svmf_put_INT_field (new_obj, end_offset, (jint) (heap->hashcode_base + (size_t) obj)); } return new_obj; } break; default: { _svmm_fatal_error ("impossible control flow"); return NULL; } break; } } } } /* -------------------------------------------------------------------------------- _svmf_free_heap -------------------------------------------------------------------------------- */ inline svm_static void _svmf_free_heap (_svmt_heap *heap) { _svmm_free(heap->space.start); } /* -------------------------------------------------------------------------------- _svmf_get_free_memory -------------------------------------------------------------------------------- */ inline svm_static size_t _svmf_get_free_memory (_svmt_heap *heap) { return (size_t) ((char *) heap->alloc.end - (char *) heap->alloc.start); } /* ---------------------------------------------------------------------- _svmf_get_hashcode_of_space ---------------------------------------------------------------------- */ inline svm_static jint _svmf_get_hashcode_of_space (_svmt_heap *heap, void *space) { return heap->hashcode_base + (size_t) space; } /* ---------------------------------------------------------------------- _svmf_get_heap_max_size ---------------------------------------------------------------------- */ inline svm_static size_t _svmf_get_heap_max_size (_svmt_heap *heap) { if (heap->max_size == 0) return SVM_JINT_MAX; else return heap->max_size; } /* ---------------------------------------------------------------------- _svmf_get_heap_size ---------------------------------------------------------------------- */ inline svm_static size_t _svmf_get_heap_size (_svmt_heap *heap) { return heap->size; } /* ---------------------------------------------------------------------- _svmf_heap_init ---------------------------------------------------------------------- */ svm_static jint _svmf_heap_init (_svmt_heap *heap) { /* if (_svmm_validate_min_max_increment (heap->min_size, heap->max_size, heap->increment_size) != JNI_OK) { return JNI_ERR; } */ /* if the heap has a fixed size, allocate both semi-spaces once and for all, if not, allocate one semi-space */ if (heap->increment_size == 0 && (2 * heap->min_size) < heap->min_size) { return JNI_ERR; } if (heap->increment_size == 0) { heap->space.start = _svmm_malloc (2 * heap->min_size); if (heap->space.start == NULL) { return JNI_ERR; } heap->space.end = ((char *) heap->space.start) + heap->min_size; heap->alloc = heap->space; heap->size = 2 * heap->min_size; heap->hashcode_base = 0 - (size_t) heap->space.start; } else { heap->space.start = _svmm_malloc (heap->min_size); heap->size = heap->min_size; if (heap->space.start == NULL) { return JNI_ERR; } heap->space.end = ((char *) heap->space.start) + heap->min_size; heap->alloc = heap->space; heap->hashcode_base = 0 - (size_t) heap->space.start; } return JNI_OK; } /* ---------------------------------------------------------------------- _svmf_heap_init_defaults ---------------------------------------------------------------------- */ svm_static void _svmf_heap_init_defaults (_svmt_heap *heap) { heap->min_size = SVM_DEFAULT_MIN_SIZE; /*SVM_HEAP_DEFAULT_MIN_SIZE; */ heap->max_size = SVM_DEFAULT_MAX_SIZE; /*SVM_HEAP_DEFAULT_MAX_SIZE; */ heap->increment_size = 4194304 * 2; #if defined (_SABLEVM_HC_STATISTICS) _svmf_init_global_gc_stat (heap); #endif /* (_SABLEVM_HC_STATISTICS) */ } #if defined (_SABLEVM_HC_STATISTICS) /* ---------------------------------------------------------------------- _svmf_print_gc_stat ---------------------------------------------------------------------- */ svm_static void _svmf_print_gc_stat (_svmt_JNIEnv *env) { _svmf_print_global_gc_stat (env); } #endif /* (_SABLEVM_HC_STATISTICS) */ /* ---------------------------------------------------------------------- _svmf_trace_heap ---------------------------------------------------------------------- */ inline svm_static void _svmf_trace_heap (_svmt_JNIEnv *env) { _svmt_heap *heap = &(env->vm->heap); _svmt_frame space; /* Trace the moved objects. */ space.start = heap->to_space.start; space.end = heap->alloc.start; while (space.start < space.end && space.end < heap->to_space.end) { _svmf_trace_space (env, &space); space.start = space.end; space.end = heap->alloc.start; } } #endif /* defined (_SABLEVM_HC_COPYING) */