blob: 16826fd0539955dc94dc5a1d27c2d93b613774dc [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Xiao-Feng Li, 2006/10/05
*/
#include "gc_thread.h"
#include "../gen/gen.h"
#include "../mark_sweep/gc_ms.h"
#include "../move_compact/gc_mc.h"
#include "../finalizer_weakref/finalizer_weakref.h"
#ifdef GC_GEN_STATS
#include "../gen/gen_stats.h"
#endif
//#define GC_OBJ_SIZE_STATISTIC
#ifdef GC_OBJ_SIZE_STATISTIC
#define GC_OBJ_SIZE_STA_MAX 256*KB
unsigned int obj_size_distribution_map[GC_OBJ_SIZE_STA_MAX>>10];
void gc_alloc_statistic_obj_distrubution(unsigned int size)
{
unsigned int sta_precision = 16*KB;
unsigned int max_sta_size = 128*KB;
unsigned int sta_current = 0;
assert(!(GC_OBJ_SIZE_STA_MAX % sta_precision));
assert(!(max_sta_size % sta_precision));
while( sta_current < max_sta_size ){
if(size < sta_current){
unsigned int index = sta_current >> 10;
obj_size_distribution_map[index] ++;
return;
}
sta_current += sta_precision;
}
unsigned int index = sta_current >> 10;
obj_size_distribution_map[index]++;
return;
}
#endif
extern Boolean mutator_need_block;
Managed_Object_Handle gc_alloc(unsigned size, Allocation_Handle ah, void *unused_gc_tls)
{
Managed_Object_Handle p_obj = NULL;
/* All requests for space should be multiples of 4 (IA32) or 8(IPF) */
assert((size % GC_OBJECT_ALIGNMENT) == 0);
assert(ah);
size = (size & NEXT_TO_HIGH_BIT_CLEAR_MASK);
Allocator* allocator = (Allocator*)gc_get_tls();
Boolean type_has_fin = type_has_finalizer((Partial_Reveal_VTable*)decode_vt((VT)ah));
if(type_has_fin && !IGNORE_FINREF && mutator_need_block)
vm_heavy_finalizer_block_mutator();
#ifdef GC_OBJ_SIZE_STATISTIC
gc_alloc_statistic_obj_distrubution(size);
#endif
#if defined(USE_UNIQUE_MARK_SWEEP_GC)
p_obj = (Managed_Object_Handle)gc_ms_alloc(size, allocator);
#elif defined(USE_UNIQUE_MOVE_COMPACT_GC)
p_obj = (Managed_Object_Handle)gc_mc_alloc(size, allocator);
#else
if ( size > GC_LOS_OBJ_SIZE_THRESHOLD ){
p_obj = (Managed_Object_Handle)los_alloc(size, allocator);
#ifdef GC_GEN_STATS
if (p_obj != NULL){
GC_Gen* gc = (GC_Gen*)allocator->gc;
gc->stats->obj_num_los_alloc++;
gc->stats->total_size_los_alloc += size;
}
#endif /* #ifdef GC_GEN_STATS */
}else{
p_obj = (Managed_Object_Handle)nos_alloc(size, allocator);
}
#endif /* defined(USE_UNIQUE_MARK_SWEEP_GC) else */
if( p_obj == NULL )
return NULL;
assert((((POINTER_SIZE_INT)p_obj) % GC_OBJECT_ALIGNMENT) == 0);
obj_set_vt((Partial_Reveal_Object*)p_obj, (VT)ah);
if(type_has_fin && !IGNORE_FINREF)
mutator_add_finalizer((Mutator*)allocator, (Partial_Reveal_Object*)p_obj);
return (Managed_Object_Handle)p_obj;
}
Managed_Object_Handle gc_alloc_fast (unsigned size, Allocation_Handle ah, void *unused_gc_tls)
{
/* All requests for space should be multiples of 4 (IA32) or 8(IPF) */
assert((size % GC_OBJECT_ALIGNMENT) == 0);
assert(ah);
if(type_has_finalizer((Partial_Reveal_VTable *) decode_vt((VT)ah)))
return NULL;
#ifdef GC_OBJ_SIZE_STATISTIC
gc_alloc_statistic_obj_distrubution(size);
#endif
Allocator* allocator = (Allocator*)gc_get_tls();
/* Try to allocate an object from the current Thread Local Block */
Managed_Object_Handle p_obj;
#if defined(USE_UNIQUE_MARK_SWEEP_GC)
p_obj = (Managed_Object_Handle)gc_ms_fast_alloc(size, allocator);
#elif defined(USE_UNIQUE_MOVE_COMPACT_GC)
if ( size > GC_LARGE_OBJ_SIZE_THRESHOLD ) return NULL;
p_obj = (Managed_Object_Handle)thread_local_alloc(size, allocator);
#else
/* object shoud be handled specially */
if ( size > GC_LOS_OBJ_SIZE_THRESHOLD ) return NULL;
p_obj = (Managed_Object_Handle)thread_local_alloc(size, allocator);
#endif
if(p_obj == NULL) return NULL;
assert((((POINTER_SIZE_INT)p_obj) % GC_OBJECT_ALIGNMENT) == 0);
obj_set_vt((Partial_Reveal_Object*)p_obj, (VT)ah);
return p_obj;
}