void Method::add_vtable_patch(void *patch)
{
    Global_Env * vm_env = VM_Global_State::loader_env;
    
    vm_env->p_vtable_patch_lock->_lock();                         // vvv

    if (_vtable_patch == NULL) {
        VTable_Patches *vp = (VTable_Patches *)STD_MALLOC(sizeof(VTable_Patches));
        memset(vp, 0, sizeof(VTable_Patches));
        _vtable_patch = vp;
    }


    VTable_Patches *curr_vp = _vtable_patch;
    for (int i = 0; i < MAX_VTABLE_PATCH_ENTRIES; i++) {
        if (curr_vp->patch_table[i] == NULL) {
            curr_vp->patch_table[i] = patch;
            vm_env->p_vtable_patch_lock->_unlock();               // ^^
            return;
        }
    }
    VTable_Patches *new_vp = (VTable_Patches *)STD_MALLOC(sizeof(VTable_Patches));
    memset(new_vp, 0, sizeof(VTable_Patches));
    new_vp->next = curr_vp;
    _vtable_patch = new_vp;
    new_vp->patch_table[0] = patch;

    vm_env->p_vtable_patch_lock->_unlock();                     // ^^^
} //Method::add_vtable_patch
Beispiel #2
0
void verifier_metadata_initialize(Heap_Verifier* heap_verifier)
{
  Heap_Verifier_Metadata* heap_verifier_metadata = (Heap_Verifier_Metadata* )STD_MALLOC(sizeof(Heap_Verifier_Metadata));
  assert(heap_verifier_metadata);
  memset(heap_verifier_metadata, 0, sizeof(Heap_Verifier_Metadata));
  
  unsigned int seg_size = GC_VERIFIER_METADATA_SIZE_BYTES + GC_VERIFIER_METADATA_BLOCK_SIZE_BYTES;
  void* metadata = STD_MALLOC(seg_size);
  assert(metadata);
  memset(metadata, 0, seg_size);
  heap_verifier_metadata->segments[0] = metadata;
  metadata = (void*)round_up_to_size((POINTER_SIZE_INT)metadata, GC_VERIFIER_METADATA_BLOCK_SIZE_BYTES);
  heap_verifier_metadata->num_alloc_segs = 1;
  
  unsigned int i = 0;
  unsigned int num_blocks = GC_VERIFIER_METADATA_SIZE_BYTES/GC_VERIFIER_METADATA_BLOCK_SIZE_BYTES;
  for(i=0; i<num_blocks; i++){
    Vector_Block* block = (Vector_Block*)((POINTER_SIZE_INT)metadata + i*GC_VERIFIER_METADATA_BLOCK_SIZE_BYTES);
    vector_block_init(block, GC_VERIFIER_METADATA_BLOCK_SIZE_BYTES);
  }
  
  unsigned num_tasks = num_blocks>>1;
  heap_verifier_metadata->free_task_pool = sync_pool_create();
  for(i=0; i<num_tasks; i++){
    Vector_Block *block = (Vector_Block*)((POINTER_SIZE_INT)metadata + i*GC_VERIFIER_METADATA_BLOCK_SIZE_BYTES);
    vector_stack_init((Vector_Block*)block);
    pool_put_entry(heap_verifier_metadata->free_task_pool, (void*)block); 
  }
  
  heap_verifier_metadata->free_set_pool = sync_pool_create();
  for(; i<num_blocks; i++){
    POINTER_SIZE_INT block = (POINTER_SIZE_INT)metadata + i*GC_VERIFIER_METADATA_BLOCK_SIZE_BYTES;    
    pool_put_entry(heap_verifier_metadata->free_set_pool, (void*)block); 
  }

  heap_verifier_metadata->mark_task_pool = sync_pool_create();
  heap_verifier_metadata->root_set_pool = sync_pool_create();
  heap_verifier_metadata->objects_pool_before_gc  = sync_pool_create();
  heap_verifier_metadata->objects_pool_after_gc     = sync_pool_create();
  heap_verifier_metadata->resurrect_objects_pool_before_gc  = sync_pool_create();
  heap_verifier_metadata->resurrect_objects_pool_after_gc      = sync_pool_create();
  heap_verifier_metadata->new_objects_pool  = sync_pool_create();  
  heap_verifier_metadata->hashcode_pool_before_gc = sync_pool_create();
  heap_verifier_metadata->hashcode_pool_after_gc = sync_pool_create();
  heap_verifier_metadata->obj_with_fin_pool= sync_pool_create();
  heap_verifier_metadata->finalizable_obj_pool= sync_pool_create();

  verifier_metadata = heap_verifier_metadata;
  heap_verifier->heap_verifier_metadata = heap_verifier_metadata;
  return;
}
Beispiel #3
0
/*Malloc and initialize fake blocks for LOS_Shrink*/
void gc_space_tuner_init_fake_blocks_for_los_shrink(GC* gc)
{
  Blocked_Space* mspace = (Blocked_Space*)gc_get_mos((GC_Gen*)gc);
  Space_Tuner* tuner = gc->tuner;
  Block_Header* mos_first_block = (Block_Header*)&mspace->blocks[0];
  unsigned int trans_blocks = (unsigned int)(tuner->tuning_size >> GC_BLOCK_SHIFT_COUNT);
  tuner->interim_blocks = (Block_Header*)STD_MALLOC(trans_blocks * sizeof(Block_Header));
  Block_Header* los_trans_fake_blocks = tuner->interim_blocks;
  memset(los_trans_fake_blocks, 0, trans_blocks * sizeof(Block_Header));
  void* trans_base = (void*)((POINTER_SIZE_INT)mos_first_block - tuner->tuning_size);
  unsigned int start_idx = GC_BLOCK_INDEX_FROM(gc->heap_start, trans_base);
  Block_Header* last_block = los_trans_fake_blocks;

  for(unsigned int i = 0; i < trans_blocks; i ++){
      Block_Header* curr_block = &los_trans_fake_blocks[i];
      curr_block->block_idx = start_idx + i;
      curr_block->base = (void*)((POINTER_SIZE_INT)trans_base + i * GC_BLOCK_SIZE_BYTES + GC_BLOCK_HEADER_SIZE_BYTES);
      curr_block->free = curr_block->base ;
      curr_block->new_free = curr_block->free;
      curr_block->ceiling = (void*)((POINTER_SIZE_INT)curr_block->base + GC_BLOCK_BODY_SIZE_BYTES);
      curr_block->status = BLOCK_COMPACTED;
#ifdef USE_32BITS_HASHCODE
      curr_block->hashcode_buf = hashcode_buf_create();
#endif
      last_block->next = curr_block;
      last_block = curr_block;
  }
  last_block->next = mos_first_block;
}
Beispiel #4
0
M2nFrame* m2n_push_suspended_frame(VM_thread* thread, Registers* regs)
{
    M2nFrame* m2nf = (M2nFrame*)STD_MALLOC(sizeof(M2nFrame));
    assert(m2nf);
    m2n_push_suspended_frame(thread, m2nf, regs);
    return m2nf;
}
Beispiel #5
0
void insert_object_location(GC_Thread *gc_thread, void *dest, Partial_Reveal_Object *p_obj)
{
    assert ((p_obj->get_obj_info() & FORWARDING_BIT_MASK) == FORWARDING_BIT_MASK); // Make sure we have the forwarding bit.
    Obj_Info_Type orig_obj_info = p_obj->get_obj_info() & ~FORWARDING_BIT_MASK; // The original obj_info without the forwarding bit set.
    if (orig_obj_info) {
        // obj_info is not zero so remember it.
        object_lock_save_info *obj_info = (object_lock_save_info *) STD_MALLOC(sizeof(object_lock_save_info));
        if (!obj_info) {
            DIE("Internal but out of c malloc space.");
        }
        // Save what needs to be restored.
        obj_info->obj_header = orig_obj_info;
        // I need to keep track of the new after-slided address
        obj_info->p_obj = (Partial_Reveal_Object *) dest;
        gc_thread->insert_object_header_info_during_sliding_compaction(obj_info);
        gc_trace (p_obj, "Object being compacted or colocated needs obj_info perserved.");
    } 

    assert ((p_obj->get_obj_info() & FORWARDING_BIT_MASK) == FORWARDING_BIT_MASK); // Make sure we have the forwarding bit.
    // clobber the header with the new address.
    assert (dest);
    assert (((POINTER_SIZE_INT)dest | FORWARDING_BIT_MASK) != (POINTER_SIZE_INT)dest); 
    // This might break on Linux if the heap is in the upper 2 gig of memory. (high bit set)
    // If it does we need to change to the low bit.

    p_obj->set_forwarding_pointer(dest);
    gc_trace (p_obj, "Insert new object location for this object");

    gc_trace (dest, "Eventual object location installed.");
}
Beispiel #6
0
GC* gc_gen_create()
{
  GC* gc = (GC*)STD_MALLOC(sizeof(GC_Gen));  
  assert(gc);
  memset(gc, 0, sizeof(GC_Gen));
  return gc;
}
// Notify the given JIT whenever this method is recompiled or initially compiled.
// The callback_data pointer will be passed back to the JIT during the callback.  
// The JIT's callback function is JIT_recompiled_method_callback.
void Method::register_jit_recompiled_method_callback(JIT *jit_to_be_notified, 
                                                     Method* caller,
                                                     void *callback_data)
{
    // Don't insert the same entry repeatedly on the _notify_recompiled_records list.
    Method_Change_Notification_Record *nr = _notify_recompiled_records;
    while (nr != NULL) {
        if (nr->equals(jit_to_be_notified, callback_data)) {
            return;
        }
        nr = nr->next;
    }

    // Insert a new notification record.
    Method_Change_Notification_Record *new_nr = 
        (Method_Change_Notification_Record *)STD_MALLOC(sizeof(Method_Change_Notification_Record));
    new_nr->caller = caller;
    new_nr->jit                = jit_to_be_notified;
    new_nr->callback_data      = callback_data;
    new_nr->next               = _notify_recompiled_records;
    _notify_recompiled_records = new_nr;

    // Record a callback in the caller method to let it unregister itself if unloaded.
    ClassLoader* this_loader = get_class()->get_class_loader();
    ClassLoader* caller_loader = caller->get_class()->get_class_loader();
    if (this_loader == caller_loader || caller_loader->IsBootstrap()) return;

    MethodSet *vec = caller->_recompilation_callbacks;
    if (vec == NULL) {
        vec = caller->_recompilation_callbacks = new MethodSet();
    }
    vec->push_back(this);
} //Method::register_jit_recompiled_method_callback
StackIterator * si_create_from_native(VM_thread * thread) {
    ASSERT_NO_INTERPRETER
    // Allocate iterator
    StackIterator * si = (StackIterator *)STD_MALLOC(sizeof(StackIterator));

    si_fill_from_native(si, thread);
    return si;
}
void gc_gen_stats_initialize(GC_Gen* gc)
{
  GC_Gen_Stats* stats = (GC_Gen_Stats*)STD_MALLOC(sizeof(GC_Gen_Stats));

  memset(stats, 0, sizeof(GC_Gen_Stats));
  stats->is_los_collected = FALSE;

  gc->stats = stats; 
}
Beispiel #10
0
void gc_space_tuner_initialize(GC* gc)
{
    Space_Tuner* tuner = (Space_Tuner*)STD_MALLOC(sizeof(Space_Tuner));
    assert(tuner);
    memset(tuner, 0, sizeof(Space_Tuner));
    tuner->kind = TRANS_NOTHING;
    tuner->tuning_size = 0;
    gc->tuner = tuner;
}
Beispiel #11
0
void sd_init_crash_handler()
{
    // Get current directory
    char buf[PATH_MAX + 1];
    char* cwd = getcwd(buf, sizeof(buf));

    if (cwd)
    {
        cwd = (char*)STD_MALLOC(strlen(cwd) + 1);
        g_curdir = cwd;
        if (cwd)
            strcpy(cwd, buf);
    }

    // Get command line
    sprintf(buf, "/proc/%d/cmdline", getpid());
    int file = open(buf, O_RDONLY);

    if (file > 0)
    {
        size_t size = 0;
        char rdbuf[256];
        ssize_t rd;
        do
        {
            rd = read(file, rdbuf, sizeof(rdbuf));
            size += (rd > 0) ? rd : 0;
        } while (rd == sizeof(rdbuf));

        if (size)
        {
            char* cmd = (char*)STD_MALLOC(size + 1);
            g_cmdline = cmd;
            if (cmd)
            {
                cmd[size] = '\0';
                lseek(file, 0, SEEK_SET);
                read(file, cmd, size);
            }
        }
        close(file);
    }
}
Beispiel #12
0
void initialize_vm_cmd_state(Global_Env *p_env, JavaVMInitArgs* arguments)
{
    p_env->vm_arguments.version = arguments->version;
    p_env->vm_arguments.nOptions = arguments->nOptions;
    p_env->vm_arguments.ignoreUnrecognized = arguments->ignoreUnrecognized;
    JavaVMOption *options = p_env->vm_arguments.options =
        (JavaVMOption*)STD_MALLOC(sizeof(JavaVMOption) * (arguments->nOptions));
    assert(options);

    memcpy(options, arguments->options, sizeof(JavaVMOption) * (arguments->nOptions));
} //initialize_vm_cmd_state
StackIterator * si_create_from_registers(Registers * regs, bool is_ip_past,
                                        M2nFrame * lm2nf) {
    ASSERT_NO_INTERPRETER
    // Allocate iterator
    StackIterator * si = (StackIterator *)STD_MALLOC(sizeof(StackIterator));
    assert(si);
    
    si_fill_from_registers(si, regs, is_ip_past, lm2nf);

    return si;
}
Beispiel #14
0
APR_DECLARE(apr_status_t) port_executable_name(char** self_name) {

    char* buf;
/*  Dhruwat - haiku porting - start */
/*#if defined(FREEBSD)*/
#if defined(FREEBSD) || defined(HAIKU)
/*  Dhruwat - haiku porting - end */
    Dl_info info;

    if (dladdr( (const void*)&main, &info) == 0) {
        return APR_ENOENT;
    }

    buf = (char*)STD_MALLOC(strlen(info.dli_fname) + 1);

    if (!buf)
        return APR_ENOMEM;

    strcpy(buf, info.dli_fname);
#else
    char tmpbuf[PATH_MAX + 1];

    int n = readlink("/proc/self/exe", tmpbuf, PATH_MAX);

    if (n == -1) {
        return apr_get_os_error();
    }

    tmpbuf[n] = '\0';

    buf = (char*)STD_MALLOC(n + 1);

    if (!buf)
        return APR_ENOMEM;

    strcpy(buf, tmpbuf);
#endif

    *self_name = buf;
    return APR_SUCCESS;
}
Beispiel #15
0
/**
 * Sets resisters to JVMTI thread
 */
void vm_set_jvmti_saved_exception_registers(vm_thread_t vm_thread,
                                            Registers* regs)
{
    assert(vm_thread);
    jvmti_thread_t jvmti_thread = &vm_thread->jvmti_thread;
    if (!jvmti_thread->jvmti_saved_exception_registers) {
        jvmti_thread->jvmti_saved_exception_registers =
            (Registers*)STD_MALLOC(sizeof(Registers));
        assert(jvmti_thread->jvmti_saved_exception_registers);
    }
    *(jvmti_thread->jvmti_saved_exception_registers) = *regs;
} // vm_set_jvmti_saved_exception_registers
Beispiel #16
0
Vector_Block* gc_verifier_metadata_extend(Pool* pool, Boolean is_set_pool)
{
  /*add a slot to pool point back to verifier_metadata, then we do not need the global var verifer_metadata*/
  lock(verifier_metadata->alloc_lock);
  Vector_Block* block = pool_get_entry(pool);
  if( block ){
    unlock(verifier_metadata->alloc_lock);
    return block;
  }
  
  unsigned int num_alloced = verifier_metadata->num_alloc_segs;
  if(num_alloced == METADATA_SEGMENT_NUM){
    printf("Run out GC metadata, please give it more segments!\n");
    exit(0);
  }
  unsigned int seg_size =  GC_VERIFIER_METADATA_EXTEND_SIZE_BYTES + GC_VERIFIER_METADATA_BLOCK_SIZE_BYTES;
  void *new_segment = STD_MALLOC(seg_size);
  assert(new_segment);
  memset(new_segment, 0, seg_size);
  verifier_metadata->segments[num_alloced] = new_segment;
  new_segment = (void*)round_up_to_size((POINTER_SIZE_INT)new_segment, GC_VERIFIER_METADATA_BLOCK_SIZE_BYTES);
  verifier_metadata->num_alloc_segs = num_alloced + 1;
  
  unsigned int num_blocks =  GC_VERIFIER_METADATA_EXTEND_SIZE_BYTES/GC_VERIFIER_METADATA_BLOCK_SIZE_BYTES;
  
  unsigned int i=0;
  for(i=0; i<num_blocks; i++){
    Vector_Block* block = (Vector_Block*)((POINTER_SIZE_INT)new_segment + i*GC_VERIFIER_METADATA_BLOCK_SIZE_BYTES);
    vector_block_init(block, GC_VERIFIER_METADATA_BLOCK_SIZE_BYTES);
    assert(vector_block_is_empty(block));
  }
  
  if(is_set_pool){
    for(i=0; i<num_blocks; i++){
      POINTER_SIZE_INT block = (POINTER_SIZE_INT)new_segment + i*GC_VERIFIER_METADATA_BLOCK_SIZE_BYTES;    
      pool_put_entry(pool, (void*)block); 
    }
  }else{
    for(i=0; i<num_blocks; i++){
      Vector_Block *block = (Vector_Block *)((POINTER_SIZE_INT)new_segment + i*GC_VERIFIER_METADATA_BLOCK_SIZE_BYTES);
      vector_stack_init(block);
      pool_put_entry(pool, (void*)block);
    }
  }

  block = pool_get_entry(pool);
  unlock(verifier_metadata->alloc_lock);
  return block;
}
void gc_gen_mode_adapt_init(GC_Gen *gc)
{
  gc->gen_mode_adaptor = (Gen_Mode_Adaptor*)STD_MALLOC( sizeof(Gen_Mode_Adaptor));
  Gen_Mode_Adaptor* gen_mode_adaptor = gc->gen_mode_adaptor;
  
  gen_mode_adaptor->gen_minor_throughput = 0.0f;
  /*reset the nongen_minor_throughput: the first default nongen minor (maybe testgc)may caused the result
  calculated to be zero. so we initial the value to 1.0f here. */
  gen_mode_adaptor->nongen_minor_throughput = 1.0f;
  gen_mode_adaptor->gen_mode_trial_count = 0;

  gen_mode_adaptor->major_survive_ratio_threshold = 1.0f;
  gen_mode_adaptor->major_repeat_count  = 1;

  gen_mode_adaptor->adapt_nos_size = min_nos_size_bytes;
}
Beispiel #18
0
void Class::setup_as_array(Global_Env* env, unsigned char num_dimensions,
    bool isArrayOfPrimitives, Class* baseClass, Class* elementClass)
{
    m_is_array = 1;
    m_num_dimensions = (unsigned char)num_dimensions;
    if(m_num_dimensions == 1) {
        m_is_array_of_primitives = isArrayOfPrimitives;
    } else {
        m_is_array_of_primitives = false;
    }
    m_array_element_class = elementClass;
    m_array_base_class = baseClass;
    m_state = ST_Initialized;

    assert(elementClass);

    // insert Java field, required by spec - 'length I'
    m_num_fields = 1;
    m_fields = new Field[1];
    m_fields[0].set(this, env->Length_String,
        env->string_pool.lookup("I"), ACC_PUBLIC|ACC_FINAL);
    m_fields[0].set_field_type_desc(
        type_desc_create_from_java_descriptor("I", NULL));
    m_fields[0].set_injected();

    m_super_class.name = env->JavaLangObject_String;
    m_super_class.cp_index = 0;

    m_access_flags = (ACC_FINAL | ACC_ABSTRACT);
    if(isArrayOfPrimitives) {
        m_access_flags |= ACC_PUBLIC;
    } else {
        // set array access flags the same as in its base class
        m_access_flags = (uint16)(m_access_flags
            | (baseClass->get_access_flags()
            & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED)));
    }
    m_package = elementClass->m_package;

    // array classes implement two interfaces: Cloneable and Serializable
    m_superinterfaces = (Class_Super*) STD_MALLOC(2 * sizeof(Class_Super));
    m_superinterfaces[0].name = env->Clonable_String;
    m_superinterfaces[0].cp_index = 0;
    m_superinterfaces[1].name = env->Serializable_String;
    m_superinterfaces[1].cp_index = 0;
    m_num_superinterfaces = 2;
}
Beispiel #19
0
// Adding dynamic generated code info to global list
void compile_add_dynamic_generated_code_chunk(const char* name, bool free_name,
    const void* address, size_t length)
{
    DynamicCode *dc = (DynamicCode *)STD_MALLOC(sizeof(DynamicCode));
    assert(dc);
    dc->name = name;
    dc->free_name = free_name;
    dc->address = address;
    dc->length = length;

    // Synchronizing access to dynamic code list
    LMAutoUnlock dcll(VM_Global_State::loader_env->p_dclist_lock);

    DynamicCode** pdcList = &VM_Global_State::loader_env->dcList;
    dc->next = *pdcList;
    *pdcList = dc;
}
Beispiel #20
0
// Create an exception from a given type and a message.
// Set cause to the current thread exception.
static void compile_raise_exception(const char* name, const char* message, Method* method)
{
    assert(hythread_is_suspend_enabled());
    jthrowable old_exc = exn_get();
    exn_clear();

    const char* c = method->get_class()->get_name()->bytes;
    const char* m = method->get_name()->bytes;
    const char* d = method->get_descriptor()->bytes;
    size_t sz = 3 + // a space, a dot, and a terminator
        strlen(message) +
        method->get_class()->get_name()->len +
        method->get_name()->len +
        method->get_descriptor()->len;
    char* msg_raw = (char*)STD_MALLOC(sz);
    assert(msg_raw);
    sprintf(msg_raw, "%s%s.%s%s", message, c, m, d);
    assert(strlen(msg_raw) < sz);

    jthrowable new_exc = exn_create(name, msg_raw, old_exc);
    exn_raise_object(new_exc);
    STD_FREE(msg_raw);
}
int port_thread_attach()
{
    int res;
    port_tls_data_t* tlsdata;

    if (!port_shared_data && (res = init_port_shared_data()) != 0)
        return res;

    if (get_private_tls_data())
        return 0;

    tlsdata = (port_tls_data_t*)STD_MALLOC(sizeof(port_tls_data_t));

    if (!tlsdata)
        return ENOMEM;

    res = port_thread_attach_local(tlsdata, FALSE, TRUE, 0);

    if (res != 0)
        STD_FREE(tlsdata);

    return res;
}
Beispiel #22
0
Class* resolve_class_array_of_class(Global_Env* env, Class* cc)
{
    // If the element type is primitive, return one of the preloaded
    // classes of arrays of primitive types.
    if (cc->is_primitive()) {
        if (cc == env->Boolean_Class) {
            return env->ArrayOfBoolean_Class;
        } else if (cc == env->Byte_Class) {
            return env->ArrayOfByte_Class;
        } else if (cc == env->Char_Class) {
            return env->ArrayOfChar_Class;
        } else if (cc == env->Short_Class) {
            return env->ArrayOfShort_Class;
        } else if (cc == env->Int_Class) {
            return env->ArrayOfInt_Class;
        } else if (cc == env->Long_Class) {
            return env->ArrayOfLong_Class;
        } else if (cc == env->Float_Class) {
            return env->ArrayOfFloat_Class;
        } else if (cc == env->Double_Class) {
            return env->ArrayOfDouble_Class;
        }
    }

    char *array_name = (char *)STD_MALLOC(cc->get_name()->len + 5);
    if(cc->get_name()->bytes[0] == '[') {
        sprintf(array_name, "[%s", cc->get_name()->bytes);
    } else {
        sprintf(array_name, "[L%s;", cc->get_name()->bytes);
    }
    String *arr_str = env->string_pool.lookup(array_name);
    STD_FREE(array_name);

    Class* arr_clss = cc->get_class_loader()->LoadVerifyAndPrepareClass(env, arr_str);

    return arr_clss;
} // resolve_class_array_of_class
void mutator_initialize(GC* gc, void *unused_gc_information) 
{
  /* FIXME:: make sure gc_info is cleared */
  Mutator *mutator = (Mutator *)STD_MALLOC(sizeof(Mutator));
  memset(mutator, 0, sizeof(Mutator));
  mutator->alloc_space = gc_get_nos((GC_Gen*)gc);
  mutator->gc = gc;
    
  if(gc_is_gen_mode()){
    mutator->rem_set = free_set_pool_get_entry(gc->metadata);
    assert(vector_block_is_empty(mutator->rem_set));
  }
  mutator->dirty_set = free_set_pool_get_entry(gc->metadata);
  
  if(!IGNORE_FINREF )
    mutator->obj_with_fin = finref_get_free_block(gc);
  else
    mutator->obj_with_fin = NULL;

#ifdef USE_UNIQUE_MARK_SWEEP_GC
  allocator_init_local_chunks((Allocator*)mutator);
#endif
  
  lock(gc->mutator_list_lock);     // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

  mutator->next = (Mutator *)gc->mutator_list;
  gc->mutator_list = mutator;
  gc->num_mutators++;
  /*Begin to measure the mutator thread execution time. */
  mutator->time_measurement_start = time_now();
  unlock(gc->mutator_list_lock); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  
  gc_set_tls(mutator);
  
  return;
}
Beispiel #24
0
void parse_vm_arguments2(Global_Env *p_env)
{
    bool version_printed = false;
#ifdef _DEBUG
    TRACE("p_env->vm_arguments.nOptions  = " << p_env->vm_arguments.nOptions);
    for (int _i = 0; _i < p_env->vm_arguments.nOptions; _i++)
        TRACE("p_env->vm_arguments.options[ " << _i << "] = " << p_env->vm_arguments.options[_i].optionString);
#endif //_DEBUG

    apr_pool_t *pool;
    apr_pool_create(&pool, 0);

    for (int i = 0; i < p_env->vm_arguments.nOptions; i++) {
        const char* option = p_env->vm_arguments.options[i].optionString;

        if (begins_with(option, XBOOTCLASSPATH)) {
            /*
             *  Override for bootclasspath - 
             *  set in the environment- the boot classloader will be responsible for 
             *  processing and setting up "vm.boot.class.path" and "sun.boot.class.path"
             *  Note that in the case of multiple arguments, the last one will be used
             */
            p_env->VmProperties()->set(XBOOTCLASSPATH, option + strlen(XBOOTCLASSPATH));
        }
        else if (begins_with(option, XBOOTCLASSPATH_A)) {
            /*
             *  addition to append to boot classpath
             *  set in environment - responsibility of boot classloader to process
             *  Note that we accumulate if multiple, appending each time
             */

            char *bcp_old = p_env->VmProperties()->get(XBOOTCLASSPATH_A);
            const char *value = option + strlen(XBOOTCLASSPATH_A);
            char *bcp_new = NULL;
            
            if (bcp_old) { 
                 char *tmp = (char *) STD_MALLOC(strlen(bcp_old) + strlen(PORT_PATH_SEPARATOR_STR)
                                                        + strlen(value) + 1);
            
                 strcpy(tmp, bcp_old);
                 strcat(tmp, PORT_PATH_SEPARATOR_STR);
                 strcat(tmp, value);
                 
                 bcp_new = tmp;
            }
            
            p_env->VmProperties()->set(XBOOTCLASSPATH_A, bcp_old ? bcp_new : value);                       
            p_env->VmProperties()->destroy(bcp_old);
            STD_FREE((void*)bcp_new);
        }
        else if (begins_with(option, XBOOTCLASSPATH_P)) {
            /*
             *  addition to prepend to boot classpath
             *  set in environment - responsibility of boot classloader to process
             *  Note that we accumulate if multiple, prepending each time
             */
             
            char *bcp_old = p_env->VmProperties()->get(XBOOTCLASSPATH_P);
            const char *value = option + strlen(XBOOTCLASSPATH_P);
            
            char *bcp_new = NULL;
            
            if (bcp_old) { 
                 char *tmp = (char *) STD_MALLOC(strlen(bcp_old) + strlen(PORT_PATH_SEPARATOR_STR)
                                                        + strlen(value) + 1);
            
                 strcpy(tmp, value);
                 strcat(tmp, PORT_PATH_SEPARATOR_STR);
                 strcat(tmp, bcp_old);
                 
                 bcp_new = tmp;
            }
            
            p_env->VmProperties()->set(XBOOTCLASSPATH_P, bcp_old ? bcp_new : value);
            p_env->VmProperties()->destroy(bcp_old);
            STD_FREE((void*)bcp_new);
        } else if (begins_with(option, "-Xjit:")) {
            // Do nothing here, just skip this option for later parsing
        } else if (strcmp(option, "-Xint") == 0) {
            p_env->VmProperties()->set("vm.use_interpreter", "true");
#ifdef VM_STATS
        } else if (begins_with(option, "-Xstats:")) {
            vm_print_total_stats = true;
            const char* arg = option + strlen("-Xstats:");
            vm_print_total_stats_level = atoi(arg);
#endif
        } else if (strcmp(option, "-version") == 0) {
            // Print the version number and exit
            LECHO_VERSION;
            log_exit(0);
        } else if (strcmp(option, "-showversion") == 0) {
            if (!version_printed) {
                // Print the version number and continue
                LECHO_VERSION;
                version_printed = true;
            }
        } else if (strcmp(option, "-fullversion") == 0) {
            // Print the version number and exit
            LECHO_VM_VERSION;
            log_exit(0);

        } else if (begins_with(option, "-Xgc:")) {
            // make prop_key to be "gc.<something>"
            char* prop_key = strdup(option + strlen("-X"));
            prop_key[2] = '.';
            TRACE(prop_key << " = 1");
            p_env->VmProperties()->set(prop_key, "1");
            free(prop_key);

        } else if (begins_with(option, "-Xem:")) {
            const char* arg = option + strlen("-Xem:");
            p_env->VmProperties()->set("em.properties", arg);

        } else if (strcmp(option, "-client") == 0 || strcmp(option, "-server") == 0) {
            p_env->VmProperties()->set("em.properties", option + 1);

        } else if (begins_with(option, "-Xms") || begins_with(option, "-ms")) {
            // cut -Xms || -ms
            const char* arg = option + (begins_with(option, "-ms") ? 3 : 4);
            TRACE("gc.ms = " << arg);
            if (atoi(arg) <= 0) {
                LECHO(34, "Negative or invalid heap size. Default value will be used!");
            }
            p_env->VmProperties()->set("gc.ms", arg);

        } else if (begins_with(option, "-Xmx") || begins_with(option, "-mx")) {
            // cut -Xmx
            const char* arg = option + (begins_with(option, "-mx") ? 3 : 4);
            TRACE("gc.mx = " << arg);
            if (atoi(arg) <= 0) {
                LECHO(34, "Negative or invalid heap size. Default value will be used!");
            }
            p_env->VmProperties()->set("gc.mx", arg);
        } else if (begins_with(option, "-Xss")) {
            const char* arg = option + 4;
            TRACE("thread.stacksize = " << arg);
            if (atoi(arg) <= 0) {
                LECHO(34, "Negative or invalid stack size. Default value will be used!");
            }
            p_env->VmProperties()->set("thread.stacksize", arg);
    	}	  
        else if (begins_with(option, STRING_POOL_SIZE_OPTION)) {
            // the pool is already created
        }
        else if (begins_with(option, "-agentlib:")) {
            p_env->TI->addAgent(option);
        }
        else if (begins_with(option, "-agentpath:")) {
            p_env->TI->addAgent(option);
        }
        else if (begins_with(option, "-javaagent:")) {
            char* dest = (char*) STD_MALLOC(strlen("-agentlib:hyinstrument=") + strlen(option + 11) + 1);
            strcpy(dest, "-agentlib:hyinstrument=");
            strcat(dest, option + 11);
            p_env->TI->addAgent(dest);
            STD_FREE((void*) dest);
        }
        else if (begins_with(option, "-Xrun")) {
            // Compatibility with JNDI
            p_env->TI->addAgent(option);
        }
        else if (strcmp(option, "-Xnoagent") == 0) {
            // Do nothing, this option is only for compatibility with old JREs
        }
        else if (strcmp(option, "-Xdebug") == 0) {
            // Do nothing, this option is only for compatibility with old JREs
        }
        else if (strcmp(option, "-Xfuture") == 0) {
            // Do nothing, this option is only for compatibility with old JREs
        }
        else if (strcmp(option, "-Xinvisible") == 0) {
            p_env->retain_invisible_annotations = true;
        }
        else if (strcmp(option, "-Xverify") == 0) {
            p_env->verify_all = true;
        }
        else if (strcmp(option, "-Xverify:none") == 0 || strcmp(option, "-noverify") == 0) {
            p_env->VmProperties()->set("vm.use_verifier", "false");
        }
        else if (strcmp(option, "-Xverify:all") == 0) {
            p_env->verify_all = true;
            p_env->verify_strict = true;
        }
        else if (strcmp(option, "-Xverify:strict") == 0) {
            p_env->verify_all = true;
            p_env->verify_strict = true;
        }
        else if (strcmp(option, "-verify") == 0) {
            p_env->verify_all = true;
        }
        else if (begins_with(option, "-verbose")) {
            // Moved to set_log_levels_from_cmd
        } else if (begins_with(option, "-Xfileline")) {
            // Moved to set_log_levels_from_cmd
        } else if (begins_with(option, "-Xthread")) {
            // Moved to set_log_levels_from_cmd
        } else if (begins_with(option, "-Xcategory")) {
            // Moved to set_log_levels_from_cmd
        } else if (begins_with(option, "-Xtimestamp")) {
            // Moved to set_log_levels_from_cmd
        } else if (begins_with(option, "-Xverbose")) {
            // Moved to set_log_levels_from_cmd
        } else if (begins_with(option, "-Xwarn")) {
            // Moved to set_log_levels_from_cmd
        } else if (begins_with(option, "-Xfunction")) {
            // Moved to set_log_levels_from_cmd
#ifdef _DEBUG
        } else if (begins_with(option, "-Xlog")) {
            // Moved to set_log_levels_from_cmd
        } else if (begins_with(option, "-Xtrace")) {
            // Moved to set_log_levels_from_cmd
#endif //_DEBUG
        }
        else if (strncmp(option, "-D", 2) == 0) {
        }
        else if (strncmp(option, "-XD", 3) == 0 || strncmp(option, "-XX:", 4) == 0) {
        }
        else if (strcmp(option, "-Xdumpstubs") == 0) {
            dump_stubs = true;
        }
        else if (strcmp(option, "-Xparallel_jit") == 0) {
            parallel_jit = true;
        }
        else if (strcmp(option, "-Xno_parallel_jit") == 0) {
            parallel_jit = false;
        }
        else if (begins_with(option, "-Xdumpfile:")) {
            const char* arg = option + strlen("-Xdumpfile:");
            dump_file_name = arg;
        }
        else if (strcmp(option, "_org.apache.harmony.vmi.portlib") == 0) {
            // Store a pointer to the portlib
            p_env->portLib = p_env->vm_arguments.options[i].extraInfo;
        }
        else if (strcmp(option, "-help") == 0 
              || strcmp(option, "-h") == 0
              || strcmp(option, "-?") == 0) {
            print_generic_help();
            log_exit(0);
        }
        else if (strcmp(option,"-X") == 0) {
                print_help_on_nonstandard_options();
                log_exit(0);
        }
        else if (begins_with(option, "-enableassertions")) {
            add_assert_rec(p_env, option, "-enableassertions", true);
        }
        else if (begins_with(option, "-ea")) { 
            add_assert_rec(p_env, option, "-ea", true);
        }
        else if (begins_with(option, "-disableassertions")) { 
            add_assert_rec(p_env, option, "-disableassertions", false);
        }
        else if (begins_with(option, "-da")) { 
            add_assert_rec(p_env, option, "-da", false);
        }
        else if (strcmp(option, "-esa") == 0 
            || strcmp(option, "-enablesystemassertions") == 0) {
            get_assert_reg(p_env)->enable_system = true;
        }
        else if (strcmp(option, "-dsa") == 0 
            || strcmp(option, "-disablesystemassertions") == 0) {
                if (p_env->assert_reg) {
                    p_env->assert_reg->enable_system = false;
                }
        }
        else {
            LECHO(30, "Unknown option {0}" << option);
            USE_JAVA_HELP;
            log_exit(1);
       }
    } // for

    apr_pool_destroy(pool);
} //parse_vm_arguments2
ncaiError JNICALL ncaiWriteMemory(ncaiEnv* env,
        void* addr, size_t size, void* buf)
{
    TRACE2("ncai.memory", "WriteMemory called");

    if (!env)
        return NCAI_ERROR_INVALID_ENVIRONMENT;

    VMBreakPoints* vm_breaks = VM_Global_State::loader_env->TI->vm_brpt;
    LMAutoUnlock lock(vm_breaks->get_lock());

    jbyte* end_addr = (jbyte*)addr + size;
    VMBreakPoint* cur;
    size_t rewrite_count = 0;

    // Count addresses in given range
    for (cur = vm_breaks->get_first_breakpoint(); cur;
         cur = vm_breaks->get_next_breakpoint(cur))
    {
        if (cur->addr >= addr && cur->addr < end_addr)
            ++rewrite_count;
    }

    // Simple case: there are no breakpoints in specified address range
    if (rewrite_count == 0)
    {
        if (port_write_memory(addr, size, buf) == 0)
            return NCAI_ERROR_NONE;
        else
            return NCAI_ERROR_ACCESS_DENIED;
    }

    // Allocate array for address sorting
    RewriteArray rwa;
    rwa.array = (BreakListItem*)STD_MALLOC(rewrite_count*sizeof(BreakListItem));

    if (!rwa.array)
        return NCAI_ERROR_OUT_OF_MEMORY;

    memset(rwa.array, 0, rewrite_count*sizeof(BreakListItem));
    rwa.list = NULL;
    rwa.size = rewrite_count;
    rwa.count = 0;

    // Add matching addresses to sorted list
    for (cur = vm_breaks->get_first_breakpoint(); cur;
         cur = vm_breaks->get_next_breakpoint(cur))
    {
        if (cur->addr >= addr && cur->addr < end_addr)
            add_rewrite_address(&rwa, cur);
    }

    // Write memory
    size_t remain = size;
    BreakListItem* cur_bla = rwa.list;
    assert(cur_bla);
    jbyte* cbuf = (jbyte*)buf;
    jbyte* cur_addr = (jbyte*)addr;
    int err = 0;

    while (remain)
    {
        if (!cur_bla || cur_bla->bp->addr > cur_addr)
        { // Write buffer to memory
            size_t offset = (size_t)cur_addr - (size_t)addr;
            size_t chunk_size = cur_bla ? ((jbyte*)cur_bla->bp->addr - cur_addr)
                                        : (end_addr - cur_addr);
            err = port_write_memory(cur_addr, chunk_size, cbuf + offset);

            if (err != 0)
                break;

            cur_addr += chunk_size;
            remain -= chunk_size;
        }

        if (cur_bla)
        { // Write byte from buffer to 'saved_byte' field in breakpoint
            assert(cur_addr == cur_bla->bp->addr);

            size_t offset = (size_t)cur_addr - (size_t)addr;
            cur_bla->bp->saved_byte = cbuf[offset];
            cur_bla = cur_bla->next;
            ++cur_addr;
            --remain;
        }
    }

    STD_FREE(rwa.array);
    return (err == 0) ? NCAI_ERROR_NONE : NCAI_ERROR_ACCESS_DENIED;
}
Beispiel #26
0
LONG NTAPI vectored_exception_handler_internal(LPEXCEPTION_POINTERS nt_exception)
{
    DWORD code = nt_exception->ExceptionRecord->ExceptionCode;
    void* fault_addr = nt_exception->ExceptionRecord->ExceptionAddress;

    Registers regs;
    // Convert NT context to Registers
    port_thread_context_to_regs(&regs, nt_exception->ContextRecord);

    // Check if TLS structure is set - probably we should produce minidump
    port_tls_data_t* tlsdata = get_private_tls_data();

    if (!tlsdata) // Tread is not attached - attach thread temporarily
    {
        int res;
        tlsdata = (port_tls_data_t*)STD_MALLOC(sizeof(port_tls_data_t));

        if (tlsdata) // Try to attach the thread
            res = port_thread_attach_local(tlsdata, TRUE, TRUE, 0);

        if (!tlsdata || res != 0)
        { // Can't process correctly; perform default actions
            if (FLAG_CORE)
                create_minidump(nt_exception);

            if (FLAG_DBG)
            {
                show_debugger_dialog(); // Workaround; EXCEPTION_CONTINUE_SEARCH does not work
                _exit(-1);
                return EXCEPTION_CONTINUE_SEARCH; // Assert dialog
            }

            _exit(-1);
        }

        // SO for alien thread can't be processed out of VEH
        if (code == STATUS_STACK_OVERFLOW &&
            sd_is_handler_registered(PORT_SIGNAL_STACK_OVERFLOW))
        {
            int result;
            size_t alt_stack_size = ALT_PAGES_COUNT*tlsdata->guard_page_size;
            void* alt_stack = map_alt_stack(alt_stack_size);
            void* stack_bottom = (void*)((POINTER_SIZE_INT)alt_stack + alt_stack_size);

            if (alt_stack)
                result = (int)(POINTER_SIZE_INT)port_call_alt_stack(
                                            port_process_signal, stack_bottom, 4,
                                            PORT_SIGNAL_STACK_OVERFLOW, &regs, fault_addr, FALSE);
            else
                result = port_process_signal(PORT_SIGNAL_STACK_OVERFLOW, &regs, fault_addr, FALSE);

            if (result == 0)
            {
                if (port_thread_detach_temporary() == 0)
                    STD_FREE(tlsdata);
                if (alt_stack)
                    unmap_alt_stack(alt_stack, alt_stack_size);
                return EXCEPTION_CONTINUE_EXECUTION;
            }

            if (FLAG_CORE)
            {
                if (alt_stack)
                    port_call_alt_stack(create_minidump, stack_bottom, 1, nt_exception);
                else
                    create_minidump(nt_exception);
            }

            if (alt_stack)
                unmap_alt_stack(alt_stack, alt_stack_size);

            if (result > 0)
            {
                show_debugger_dialog(); // Workaround; EXCEPTION_CONTINUE_SEARCH does not work
                _exit(-1);
                shutdown_signals();
                return EXCEPTION_CONTINUE_SEARCH; // Assert dialog
            }

            _exit(-1);
        }
    }

    if (tlsdata->produce_core)
    {
        create_minidump(nt_exception);
        if (!tlsdata->debugger)
            _exit(-1);
    }

    if (tlsdata->debugger)
    {
        show_debugger_dialog(); // Workaround
        _exit(-1);
        // Go to handler to restore CRT/VEH settings and crash once again
//        port_set_longjump_regs(&prepare_assert_dialog, &regs, 1, &regs);
//        port_thread_regs_to_context(nt_exception->ContextRecord, &regs);
//        return EXCEPTION_CONTINUE_EXECUTION;
    }

    switch (code)
    {
    case STATUS_STACK_OVERFLOW:
        if (!sd_is_handler_registered(PORT_SIGNAL_STACK_OVERFLOW))
            return EXCEPTION_CONTINUE_SEARCH;
        break;
    case STATUS_ACCESS_VIOLATION:
        if (!sd_is_handler_registered(PORT_SIGNAL_GPF))
            return EXCEPTION_CONTINUE_SEARCH;
        break;
    case JVMTI_EXCEPTION_STATUS:
        if (!sd_is_handler_registered(PORT_SIGNAL_BREAKPOINT))
            return EXCEPTION_CONTINUE_SEARCH;
        break;
    case STATUS_INTEGER_DIVIDE_BY_ZERO:
    case EXCEPTION_FLT_DIVIDE_BY_ZERO:
    case EXCEPTION_FLT_OVERFLOW:
    case EXCEPTION_FLT_UNDERFLOW:
    case EXCEPTION_INT_OVERFLOW:
        if (!sd_is_handler_registered(PORT_SIGNAL_ARITHMETIC))
            return EXCEPTION_CONTINUE_SEARCH;
        break;
    default:
        return EXCEPTION_CONTINUE_SEARCH;
    }

    if (code == STATUS_STACK_OVERFLOW)
    {
        tlsdata->guard_page_set = FALSE; // GUARD_PAGE was cleared by OS

        if (!tlsdata->restore_guard_page)
            tlsdata->restore_guard_page = TRUE;
    }

    // Prepare to transfering control out of VEH handler
    port_set_longjump_regs(&c_handler, &regs, 4, &regs,
        nt_exception->ExceptionRecord->ExceptionAddress,
        (void*)(size_t)nt_exception->ExceptionRecord->ExceptionCode,
        (void*)(size_t)nt_exception->ExceptionRecord->ExceptionFlags);
    // Convert prepared Registers back to NT context
    port_thread_regs_to_context(nt_exception->ContextRecord, &regs);
    // Return from VEH - presumably continue execution
    return EXCEPTION_CONTINUE_EXECUTION;
}
Beispiel #27
0
//
// Input/Output next_obj_start_arg - a pointer to a pointer to where the
//  fused objects will eventually reside. Updated to the end of the fused
//  objects.
//
bool fuse_objects (GC_Thread *gc_thread,
                   Partial_Reveal_Object *p_obj,
                   void **next_obj_start_arg,
                   unsigned int *problem_locks)
{


    bool UNUSED debug_printf_trigger = false;

    unsigned int            moved_count = 0;
    unsigned int            unmoved_count = 0;
    // If we can fuse an object we do and return it.
    assert (p_obj->vt()->get_gcvt()->gc_fuse_info);
    gc_trace (p_obj, "This object is a candidate for fusing with next object.");
    
    Partial_Reveal_Object   *scan_stack[MAX_FUSABLE_OBJECT_SCAN_STACK];
    unsigned                top = 0;
    
    Partial_Reveal_Object   *fuse_queue[MAX_FUSED_OBJECT_COUNT];
    unsigned                last = 0;
    
    scan_stack[top++] = p_obj;
    unsigned int fused_size = get_object_size_bytes(p_obj);
    unsigned int base_obj_size = fused_size;

    void *to_obj = *next_obj_start_arg;
    void * UNUSED debug_orig_to_obj = to_obj;
    
    // Claim the Forwading bit if you can. If you loose the race you can't fuse since someone else is.
    Obj_Info_Type old_base_value = p_obj->get_obj_info();
    Obj_Info_Type new_base_value = old_base_value;
    if ((old_base_value & FORWARDING_BIT_MASK) == FORWARDING_BIT_MASK)  {
        return false; // Some other thread is going to move this object.
    }

    new_base_value = old_base_value | FORWARDING_BIT_MASK;
    
    if (p_obj->compare_exchange(new_base_value, old_base_value) != old_base_value) {
        // We did not get the forwarding pointer successfully, some other thread got it.
        // Since this is the base object we can just return false.
        return false;
    }
    
    // Build a queue of objects to colocate but do not grab the FORWARDING_BIT until the queue is built.
    while (top > 0) {
        Partial_Reveal_Object *p_cur_obj = scan_stack[--top];
        int *offset_scanner = init_fused_object_scanner(p_cur_obj);
        Slot pp_next_object(NULL);
        Partial_Reveal_Object *p_last_object = p_obj;
        while (pp_next_object.set(p_get_ref(offset_scanner, p_cur_obj)) != NULL) {
            // Move the scanner to the next reference.
            offset_scanner = p_next_ref (offset_scanner);
            // This object is to be fused with the object located at the gc_fuse_info so calculate the required size.
            Partial_Reveal_Object *p_next_from_obj = pp_next_object.dereference();
            gc_trace (p_next_from_obj, "This object is a candidate to be fused with previous object.");
            
            if (p_next_from_obj) {
                // Check NULL.
                block_info *fuse_block_info = GC_BLOCK_INFO(p_next_from_obj);
                void * next_natural_obj = (void *) (POINTER_SIZE_INT(p_last_object) + get_object_size_bytes(p_last_object));
                Obj_Info_Type new_value = p_next_from_obj->get_obj_info();
                bool is_colocation_natural = (next_natural_obj == (void *)p_next_from_obj);
                bool overflow = (((POINTER_SIZE_INT)to_obj + fused_size + get_object_size_bytes(p_next_from_obj)) > (POINTER_SIZE_INT)(GC_BLOCK_CEILING(to_obj)));
                    
                bool already_forwarded = ((new_value & FORWARDING_BIT_MASK) == FORWARDING_BIT_MASK);
                bool in_compaction_block = gc_thread->_p_gc->is_compaction_block(fuse_block_info);
                
                bool can_fuse = ((!already_forwarded)
                    && (!is_colocation_natural)
                    && (!overflow)
                    && in_compaction_block
                    );

                if (can_fuse){                
                    if (p_next_from_obj->vt()->get_gcvt()->gc_fuse_info) {
                        scan_stack[top++] = p_next_from_obj;
                    }
                
                    fuse_queue[last] = p_next_from_obj;
                
                    fused_size += get_object_size_bytes(p_next_from_obj);
                    last++;
                } else {
                    p_obj->set_obj_info(old_base_value); // Release the forwarding bit and don't colocate this object.
                     return false;
                }  
            }
        }
    }

    unsigned i;
    // Grab the forwarding bits for the other object in the queue.. If you can't get a bit 
    // remove the object from the queue.
    for (i = 0; i < last; i++) {
        Partial_Reveal_Object *p_fuse_obj = fuse_queue[i];
        Obj_Info_Type new_value = p_fuse_obj->get_obj_info();
        Obj_Info_Type old_value = new_value; 
        bool already_forwarded = ((new_value & FORWARDING_BIT_MASK) == FORWARDING_BIT_MASK);
        new_value = old_value | FORWARDING_BIT_MASK; // Create the value with a the forwarding bit set.
        if (!already_forwarded) {
            // install the forwarding bit if it has not already been forwarded.
            already_forwarded = (p_fuse_obj->compare_exchange(new_value, old_value) != old_value);
        }

        if (already_forwarded) {

            debug_printf_trigger = true;
            TRACE("REMOVING FROM FUSE QUEUE.");
            // Remove this object from the queue since we can colocate it.
            unsigned int j;
            for (j = i; j < last - 1; j++) {
                fuse_queue[j] = fuse_queue[j+1];
            }
            // We have one less object on the queue.
            fuse_queue[last] = NULL;
            last--;
            i--; // Redo since fuse_queue[i] now holds a new object.
            unmoved_count++;
        }
        gc_trace (p_fuse_obj, "No space so this object is not fused with parent.");
    }

    // We don't fuse more than a single block worth of objects.
    assert (fused_size <= GC_BLOCK_ALLOC_SIZE);
    // We own all the forwarding bits in all the objects in the fuse_queue.
    
    // If we only have the base object and no other object to colocate with it just return.
    if (last == 0) {
        p_obj->set_obj_info(old_base_value); // Release the forwarding bit and don't colocate this object.
        // No objects to relocate.
        TRACE("3");
        return false;
    }
    
    // At this point all objects in the queue will be fused, we have the forwarding bits 
    // so we now figure out where they will be colocated.
    
    gc_trace (p_obj, "Fusing this object with offspring.");
    assert ((POINTER_SIZE_INT)(GC_BLOCK_INFO (to_obj + get_object_size_bytes(p_obj) - 1)) <= (POINTER_SIZE_INT)(GC_BLOCK_CEILING(to_obj)));
    assert ((p_obj->get_obj_info() & FORWARDING_BIT_MASK) == FORWARDING_BIT_MASK);
 
    if (object_info_is_not_zero(p_obj)) {
            if ((p_obj->get_obj_info() & ~FORWARDING_BIT_MASK) != 0) {
                object_lock_save_info *obj_info = (object_lock_save_info *) STD_MALLOC(sizeof(object_lock_save_info));
                assert(obj_info);
                // Save what needs to be restored.
                obj_info->obj_header = p_obj->get_obj_info();
                obj_info->obj_header = obj_info->obj_header & ~FORWARDING_BIT_MASK; // Clear forwarding bit.
                // I need to keep track of the new after-slided address
                obj_info->p_obj = (Partial_Reveal_Object *) to_obj;
                gc_thread->insert_object_header_info_during_sliding_compaction(obj_info);
                *problem_locks = *problem_locks + 1;; // placement code does not deal with this so this is likely to be wrong.
                gc_trace (p_obj, "Object being fused needs obj_info preserved.");
                debug_printf_trigger = true;
                INFO("preserving base fused object header");
            }
        }

    // Finally deal with this placement, moving the base object first.
    insert_object_location (gc_thread, to_obj, p_obj);
    gc_trace (to_obj, " In allocate_forwarding_pointers_for_compaction_live_objects forwarding *to* this location. (vtable not yet legal)");
    gc_trace(p_obj, " was forwarded...");
    if (verify_live_heap) {
        add_repointed_info_for_thread(p_obj, (Partial_Reveal_Object *) to_obj, gc_thread->get_id());
    }

    assert (base_obj_size == get_object_size_bytes(p_obj));
    to_obj = (void *) ((POINTER_SIZE_INT) to_obj + base_obj_size);
    
    // Now figure out where the referent objects belong and set up their forwarding pointers.
    
    for (i = 0; i < last; i++) {
        Partial_Reveal_Object *p_fuse_obj = fuse_queue[i];
        unsigned int fused_obj_size = get_object_size_bytes(p_fuse_obj); 
        gc_trace (p_fuse_obj, "Fusing this object with parent.");
        // Finally deal with this colocations.
        assert (p_fuse_obj != p_obj); // Nulls should have been filtered out up above.
        
        if (object_info_is_not_zero(p_fuse_obj)) {
            if ((p_fuse_obj->get_obj_info() & ~FORWARDING_BIT_MASK) != 0) {
                object_lock_save_info *obj_info = (object_lock_save_info *) STD_MALLOC(sizeof(object_lock_save_info));
                assert(obj_info);
                // Save what needs to be restored.
                obj_info->obj_header = p_fuse_obj->get_obj_info();
                obj_info->obj_header = obj_info->obj_header & ~FORWARDING_BIT_MASK; // Clear forwarding bit.
                // I need to keep track of the new after-slided address
                obj_info->p_obj = (Partial_Reveal_Object *) to_obj;
                gc_thread->insert_object_header_info_during_sliding_compaction(obj_info);
                *problem_locks = *problem_locks + 1;; // placement code does not deal with this so this is likely to be wrong.
                gc_trace (p_fuse_obj, "Object being fused needs obj_info preserved.");
                debug_printf_trigger = true;
                INFO("preserving fused object header");
            }
        }
        
        // Counts are not thread safe but it is just an approximation....
        moved_count++;

        // The object in the queue its forwarding bit set.
        {
            POINTER_SIZE_INT UNUSED next_available = (POINTER_SIZE_INT)to_obj + get_object_size_bytes(p_fuse_obj) -1;
            assert ((fuse_queue[i]->get_obj_info() & FORWARDING_BIT_MASK) == FORWARDING_BIT_MASK);
            assert (next_available <=  ((POINTER_SIZE_INT)(GC_BLOCK_CEILING(to_obj))));
        }
        insert_object_location(gc_thread, to_obj, p_fuse_obj);
        gc_trace (to_obj, " In allocate_forwarding_pointers_for_compaction_live_objects forwarding *to* this location. (vtable not yet legal)");
        gc_trace(p_obj, " was forwarded...");
        if (verify_live_heap) {
            add_repointed_info_for_thread(p_fuse_obj, (Partial_Reveal_Object *) to_obj, gc_thread->get_id());
        }
 
        to_obj = (void *) ((POINTER_SIZE_INT) to_obj + fused_obj_size);
    }

    *next_obj_start_arg = to_obj; // Update and return.
    TRACE("next_obj_start_arg addr: " << next_obj_start_arg 
        << ", old_val " << debug_orig_to_obj << ", new_val " << to_obj);
    return true;
}       
int port_thread_create(/* out */osthread_t* phandle, size_t stacksize, int priority,
        port_threadfunc_t func, void *data)
{
    pthread_t thread;
    pthread_attr_t attr;
    pthread_attr_t attr_nosched;
    struct sched_param param;
    thread_start_struct_t* startstr;
    int res;

    if (!port_shared_data)
    {
        res = init_port_shared_data();
        /* assert(res); */
        /* It's OK to have an error here when Port shared library
           is not available yet; only signals/crash handling will
           not be available for the thread */
        /* return res; */
    }

    if (!func)
        return EINVAL;

    startstr =
        (thread_start_struct_t*)STD_MALLOC(sizeof(thread_start_struct_t));

    if (!startstr)
        return ENOMEM;

    pthread_attr_init(&attr);
    pthread_attr_init(&attr_nosched);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    pthread_attr_setdetachstate(&attr_nosched, PTHREAD_CREATE_DETACHED);

    if (stacksize != 0)
    {
        if (stacksize < MINSIGSTKSZ)
            stacksize = MINSIGSTKSZ;

        if (port_shared_data)
        {
            size_t min_stacksize =
                /* Let's get alt stack size for normal stack and add guard page size */
                ((2*port_shared_data->guard_stack_size + port_shared_data->guard_page_size)
                /* Roung up to alt stack size */
                    + port_shared_data->guard_stack_size - 1) & ~(port_shared_data->guard_stack_size - 1);

            if (stacksize < min_stacksize)
                stacksize = min_stacksize;
        }

        res = pthread_attr_setstacksize(&attr, stacksize);
        if (res == 0)
            res = pthread_attr_setstacksize(&attr_nosched, stacksize);
        if (res)
        {
            pthread_attr_destroy(&attr);
            pthread_attr_destroy(&attr_nosched);
            STD_FREE(startstr);
            return res;
        }
    }

    if (priority)
    {
        res = pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
        if (res == 0)
        {
            param.sched_priority = priority;
            res = pthread_attr_setschedparam(&attr, &param);
        }
        /* This does not work anyway on some Linuses
        if (res != 0)
        {
            pthread_attr_destroy(&attr);
            pthread_attr_destroy(&attr_nosched);
            STD_FREE(startstr);
            return res;
        }*/
    }

    startstr->fun = func;
    startstr->arg = data;
    startstr->stack_size = stacksize;

    res = pthread_create(&thread, &attr, (pthread_func_t)thread_start_func, startstr);

    if (res == EPERM) // EPERM relates to scheduling only
        res = pthread_create(&thread, &attr_nosched, (pthread_func_t)thread_start_func, startstr);

    pthread_attr_destroy(&attr);
    pthread_attr_destroy(&attr_nosched);

    if (res == 0)
    {
        *phandle = thread;
        return 0;
    }

    STD_FREE(startstr);
    return res;
}
void gc_gen_collector_stats_initialize(Collector* collector)
{
  GC_Gen_Collector_Stats* stats = (GC_Gen_Collector_Stats*)STD_MALLOC(sizeof(GC_Gen_Collector_Stats));
  memset(stats, 0, sizeof(GC_Gen_Collector_Stats));
  collector->stats = (void*)stats; 
}
/*
 * Class:     java_lang_VMClassRegistry
 * Method:    getSystemPackages
 * Signature: (I)[[Ljava/lang/String;
 */
JNIEXPORT jobjectArray JNICALL Java_java_lang_VMClassRegistry_getSystemPackages
  (JNIEnv *jenv, jclass, jint len)
{
    Global_Env* genv = VM_Global_State::loader_env;
    ClassLoader* cl = static_cast<ClassLoader*>
        (genv->bootstrap_class_loader);
    Package_Table* ptab = cl->getPackageTable();
    cl->Lock();
    unsigned p_num = (unsigned)ptab->size();
    if (p_num == (unsigned)len) 
    {
        cl->Unlock();
        return NULL;
    }
    const char ** pkgs = (const char **)STD_MALLOC(p_num * 2 * sizeof(char*));
    size_t buf_len = 0;
    unsigned index = 0;
    for (Package_Table::const_iterator it = ptab->begin(), end = ptab->end(); 
        it != end; ++it)
    {
        const char* name = pkgs[index++] = (*it).first->bytes;
        pkgs[index++] = (*it).second->get_jar();
        size_t name_len = (*it).first->len;
        if (name_len > buf_len) {
            buf_len = name_len;
        }
    }
    cl->Unlock();

    jclass string_class = struct_Class_to_java_lang_Class_Handle(genv->JavaLangString_Class);
    static Class* aos = genv->LoadCoreClass("[Ljava/lang/String;");
    jclass string_array_class = struct_Class_to_java_lang_Class_Handle(aos);
    assert(string_class);
    assert(string_array_class);
        
    jobjectArray result = NewObjectArray(jenv, p_num, string_array_class, NULL);
    if (result) 
    {
        char* buf = (char*)STD_MALLOC(buf_len + 1);
        p_num *= 2;
        for (index = 0; index < p_num; )
        {
            jobjectArray pair = NewObjectArray(jenv, 2, string_class, NULL);
            if (!pair) {
                break;
            }
            SetObjectArrayElement(jenv, result, index/2, pair);

            char* name = strcpy(buf, pkgs[index++]);
            for (char* c = name; *c != '\0'; ++c) {
                if (*c == '/') {
                    *c = '.';
                }
            }
            jstring jname = NewStringUTF(jenv, name);
            if (!jname) {
                break;
            }
            SetObjectArrayElement(jenv, pair, 0, jname);

            const char * jar = pkgs[index++];
            if (jar) {
                jstring js = NewStringUTF(jenv, jar);
                if (!js) break;
                SetObjectArrayElement(jenv, pair, 1, js);
            }
        }
        STD_FREE(buf);
    }

    STD_FREE(pkgs);
    
    assert(result || exn_raised());
    return result;
}