a2828bff8b
Former-commit-id: 8ff468edef2b5377f24097610316870b85491049
262 lines
7.9 KiB
C
262 lines
7.9 KiB
C
/*
|
|
* Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
|
|
* Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.
|
|
*
|
|
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
|
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
|
*
|
|
* Permission is hereby granted to use or copy this program
|
|
* for any purpose, provided the above notices are retained on all copies.
|
|
* Permission to modify the code and to distribute modified code is granted,
|
|
* provided the above notices are retained, and a notice that the code was
|
|
* modified is included with the above copyright notice.
|
|
*
|
|
*/
|
|
|
|
#include "private/gc_pmark.h" /* includes gc_priv.h */
|
|
|
|
#ifdef GC_GCJ_SUPPORT
|
|
|
|
/*
|
|
* This is an allocator interface tuned for gcj (the GNU static
|
|
* java compiler).
|
|
*
|
|
* Each allocated object has a pointer in its first word to a vtable,
|
|
* which for our purposes is simply a structure describing the type of
|
|
* the object.
|
|
* This descriptor structure contains a GC marking descriptor at offset
|
|
* MARK_DESCR_OFFSET.
|
|
*
|
|
* It is hoped that this interface may also be useful for other systems,
|
|
* possibly with some tuning of the constants. But the immediate goal
|
|
* is to get better gcj performance.
|
|
*
|
|
* We assume:
|
|
* 1) Counting on explicit initialization of this interface is OK;
|
|
* 2) FASTLOCK is not a significant win.
|
|
*/
|
|
|
|
#include "gc_vector.h"
|
|
#include "private/dbg_mlc.h"
|
|
#include "gc_typed.h"
|
|
|
|
#ifdef GC_ASSERTIONS
|
|
GC_INNER /* variable is also used in thread_local_alloc.c */
|
|
#else
|
|
STATIC
|
|
#endif
|
|
GC_bool GC_gcj_vector_initialized = FALSE;
|
|
|
|
int GC_gcj_vector_kind = 0; /* Object kind for objects with descriptors */
|
|
/* in "vtable". */
|
|
|
|
int GC_gcj_vector_mp_index = 0;
|
|
|
|
GC_INNER ptr_t * GC_gcjvecfreelist = NULL;
|
|
|
|
/* Caller does not hold allocation lock. */
|
|
GC_API void GC_CALL GC_init_gcj_vector (int mp_index,
|
|
void * /* really GC_mark_proc */mp)
|
|
{
|
|
DCL_LOCK_STATE;
|
|
|
|
if (mp == 0) /* In case GC_DS_PROC is unused. */
|
|
ABORT ("GC_init_gcj_vector: bad index");
|
|
|
|
GC_init (); /* In case it's not already done. */
|
|
LOCK ();
|
|
if (GC_gcj_vector_initialized) {
|
|
UNLOCK ();
|
|
return;
|
|
}
|
|
GC_gcj_vector_initialized = TRUE;
|
|
GC_gcj_vector_mp_index = mp_index;
|
|
GC_ASSERT (GC_mark_procs[mp_index] == (GC_mark_proc)0); /* unused */
|
|
GC_mark_procs[mp_index ] = (GC_mark_proc)(word)mp;
|
|
if ((unsigned)mp_index >= GC_n_mark_procs)
|
|
ABORT ("GC_init_gcj_vector: bad index");
|
|
GC_gcjvecfreelist = (ptr_t *)GC_new_free_list_inner ();
|
|
GC_gcj_vector_kind = GC_new_kind_inner ((void **)GC_gcjvecfreelist,
|
|
GC_MAKE_PROC (mp_index,
|
|
0),
|
|
FALSE, TRUE);
|
|
|
|
UNLOCK ();
|
|
}
|
|
|
|
#define GENERAL_MALLOC_INNER(lb,k) \
|
|
GC_clear_stack(GC_generic_malloc_inner(lb, k))
|
|
|
|
#define GENERAL_MALLOC_INNER_IOP(lb,k) \
|
|
GC_clear_stack(GC_generic_malloc_inner_ignore_off_page(lb, k))
|
|
|
|
#if !IL2CPP_ENABLE_WRITE_BARRIER_VALIDATION
|
|
#ifdef THREAD_LOCAL_ALLOC
|
|
GC_INNER void * GC_gcj_vector_malloc(size_t lb,
|
|
void * ptr_to_struct_containing_descr)
|
|
#else
|
|
GC_API GC_ATTR_MALLOC void * GC_CALL GC_gcj_vector_malloc (size_t lb,
|
|
void * ptr_to_struct_containing_descr)
|
|
#endif
|
|
{
|
|
ptr_t op;
|
|
DCL_LOCK_STATE;
|
|
|
|
GC_DBG_COLLECT_AT_MALLOC (lb);
|
|
if (SMALL_OBJ (lb)) {
|
|
word lg;
|
|
|
|
LOCK ();
|
|
lg = GC_size_map[lb];
|
|
op = GC_gcjvecfreelist[lg];
|
|
if (EXPECT (0 == op, FALSE)) {
|
|
maybe_finalize ();
|
|
op = (ptr_t)GENERAL_MALLOC_INNER ((word)lb, GC_gcj_vector_kind);
|
|
if (0 == op) {
|
|
GC_oom_func oom_fn = GC_oom_fn;
|
|
UNLOCK ();
|
|
return((*oom_fn)(lb));
|
|
}
|
|
}
|
|
else {
|
|
GC_gcjvecfreelist[lg] = (ptr_t)obj_link (op);
|
|
GC_bytes_allocd += GRANULES_TO_BYTES ((word)lg);
|
|
}
|
|
GC_ASSERT (((void **)op)[1] == 0);
|
|
}
|
|
else {
|
|
LOCK ();
|
|
maybe_finalize ();
|
|
op = (ptr_t)GENERAL_MALLOC_INNER ((word)lb, GC_gcj_vector_kind);
|
|
if (0 == op) {
|
|
GC_oom_func oom_fn = GC_oom_fn;
|
|
UNLOCK ();
|
|
return((*oom_fn)(lb));
|
|
}
|
|
}
|
|
*(void **)op = ptr_to_struct_containing_descr;
|
|
UNLOCK ();
|
|
GC_dirty (op);
|
|
return((void *)op);
|
|
}
|
|
#define ELEMENT_CHUNK_SIZE 256
|
|
|
|
GC_API mse *GC_CALL
|
|
GC_gcj_vector_mark_proc (mse *mark_stack_ptr, mse* mark_stack_limit, GC_descr element_desc, word *start, word *end, int words_per_element)
|
|
{
|
|
/* create new descriptor that is shifted two bits to account
|
|
* for lack of object header. Descriptors for value types include
|
|
* the object header for boxed values */
|
|
|
|
/* remove tags */
|
|
GC_descr element_desc_shifted = element_desc & ~(GC_DS_TAGS);
|
|
/* shift actual bits */
|
|
element_desc_shifted = element_desc_shifted << 2;
|
|
/* shifted and unmasked desc to use for bulk processing */
|
|
GC_descr element_desc_shifted_unmasked = element_desc_shifted;
|
|
/* add back tag to indicate descriptor is a bitmap */
|
|
element_desc_shifted |= GC_DS_BITMAP;
|
|
|
|
size_t remaining_elements = (end - start) / words_per_element;
|
|
|
|
/* attempt to bulk process multiple elements with single descriptor */
|
|
size_t elements_per_desc = (CPP_WORDSZ - GC_DS_TAG_BITS) / words_per_element;
|
|
|
|
if (mark_stack_ptr >= mark_stack_limit)
|
|
return GC_signal_mark_stack_overflow (mark_stack_ptr);
|
|
|
|
/* setup bulk processing */
|
|
if (elements_per_desc > 1) {
|
|
word *current = start;
|
|
size_t bulk_count = remaining_elements / elements_per_desc;
|
|
size_t remainder_count = remaining_elements % elements_per_desc;
|
|
|
|
/* bulk processing */
|
|
if (bulk_count) {
|
|
size_t bulk_stride = elements_per_desc * words_per_element;
|
|
GC_descr bulk_desc = 0;
|
|
size_t i;
|
|
for (i = 0; i < elements_per_desc; ++i) {
|
|
bulk_desc |= element_desc_shifted_unmasked >> (i * words_per_element);
|
|
}
|
|
bulk_desc |= GC_DS_BITMAP;
|
|
|
|
if (bulk_count > ELEMENT_CHUNK_SIZE) {
|
|
bulk_count = ELEMENT_CHUNK_SIZE;
|
|
|
|
/* only process chunk number of items */
|
|
end = start + bulk_count * bulk_stride;
|
|
|
|
remainder_count = 0;
|
|
|
|
mark_stack_ptr++;
|
|
if (mark_stack_ptr >= mark_stack_limit)
|
|
mark_stack_ptr = GC_signal_mark_stack_overflow (mark_stack_ptr);
|
|
mark_stack_ptr->mse_descr.w = GC_MAKE_PROC (GC_gcj_vector_mp_index, 1 /* continue processing */);
|
|
mark_stack_ptr->mse_start = (ptr_t)end;
|
|
}
|
|
|
|
while (bulk_count > 0) {
|
|
mark_stack_ptr++;
|
|
if (mark_stack_ptr >= mark_stack_limit)
|
|
mark_stack_ptr = GC_signal_mark_stack_overflow (mark_stack_ptr);
|
|
|
|
mark_stack_ptr->mse_start = (ptr_t) (current);
|
|
mark_stack_ptr->mse_descr.w = bulk_desc;
|
|
|
|
current += bulk_stride;
|
|
|
|
bulk_count--;
|
|
}
|
|
}
|
|
|
|
while (remainder_count > 0) {
|
|
mark_stack_ptr++;
|
|
if (mark_stack_ptr >= mark_stack_limit)
|
|
mark_stack_ptr = GC_signal_mark_stack_overflow (mark_stack_ptr);
|
|
|
|
mark_stack_ptr->mse_start = (ptr_t) (current);
|
|
mark_stack_ptr->mse_descr.w = element_desc_shifted;
|
|
|
|
current += words_per_element;
|
|
|
|
remainder_count--;
|
|
}
|
|
} else {
|
|
size_t remainder_count = remaining_elements;
|
|
|
|
if (remainder_count > ELEMENT_CHUNK_SIZE) {
|
|
remainder_count = ELEMENT_CHUNK_SIZE;
|
|
|
|
/* only process chunk number of items */
|
|
end = start + remainder_count * words_per_element;
|
|
|
|
mark_stack_ptr++;
|
|
if (mark_stack_ptr >= mark_stack_limit)
|
|
mark_stack_ptr = GC_signal_mark_stack_overflow (mark_stack_ptr);
|
|
|
|
mark_stack_ptr->mse_descr.w = GC_MAKE_PROC (GC_gcj_vector_mp_index, 1 /* continue processing */);
|
|
mark_stack_ptr->mse_start = (ptr_t)end;
|
|
}
|
|
|
|
word *current = start;
|
|
while (remainder_count > 0) {
|
|
mark_stack_ptr++;
|
|
if (mark_stack_ptr >= mark_stack_limit)
|
|
mark_stack_ptr = GC_signal_mark_stack_overflow (mark_stack_ptr);
|
|
|
|
mark_stack_ptr->mse_start = (ptr_t) (current);
|
|
mark_stack_ptr->mse_descr.w = element_desc_shifted;
|
|
|
|
current += words_per_element;
|
|
|
|
remainder_count--;
|
|
}
|
|
}
|
|
|
|
return (mark_stack_ptr);
|
|
}
|
|
#endif
|
|
|
|
#endif /* GC_GCJ_SUPPORT */
|