/* Initializes a new thread context. Note that this doesn't set up a * thread itself, it just creates the data structure that exists in * MoarVM per thread. */ MVMThreadContext * MVM_tc_create(MVMThreadContext *parent, MVMInstance *instance) { MVMThreadContext *tc = MVM_calloc(1, sizeof(MVMThreadContext)); MVMint32 i; /* Associate with VM instance. */ tc->instance = instance; /* Set up GC nursery. We only allocate tospace initially, and allocate * fromspace the first time this thread GCs, provided it ever does. */ tc->nursery_tospace_size = MVM_gc_new_thread_nursery_size(instance); tc->nursery_tospace = MVM_calloc(1, tc->nursery_tospace_size); tc->nursery_alloc = tc->nursery_tospace; tc->nursery_alloc_limit = (char *)tc->nursery_alloc + tc->nursery_tospace_size; /* Set up temporary root handling. */ tc->num_temproots = 0; tc->alloc_temproots = MVM_TEMP_ROOT_BASE_ALLOC; tc->temproots = MVM_malloc(sizeof(MVMCollectable **) * tc->alloc_temproots); /* Set up intergenerational root handling. */ tc->num_gen2roots = 0; tc->alloc_gen2roots = 64; tc->gen2roots = MVM_malloc(sizeof(MVMCollectable *) * tc->alloc_gen2roots); /* Set up the second generation allocator. */ tc->gen2 = MVM_gc_gen2_create(instance); /* The fixed size allocator also keeps pre-thread state. */ MVM_fixed_size_create_thread(tc); /* Allocate an initial call stack region for the thread. */ MVM_callstack_region_init(tc); /* Initialize random number generator state. */ MVM_proc_seed(tc, (MVM_platform_now() / 10000) * MVM_proc_getpid(tc)); /* Allocate temporary big integers. */ for (i = 0; i < MVM_NUM_TEMP_BIGINTS; i++) { tc->temp_bigints[i] = MVM_malloc(sizeof(mp_int)); mp_init(tc->temp_bigints[i]); } /* Initialize frame sequence numbers */ tc->next_frame_nr = 0; tc->current_frame_nr = 0; /* Initialize last_payload, so we can be sure it's never NULL and don't * need to check. */ tc->last_payload = instance->VMNull; /* Initialize plugin_guard_args so we never have to do a NULL check */ tc->plugin_guard_args = instance->VMNull; /* Note that these two assignments above are repeated in * MVM_6model_bootstrap because VMNull doesn't exist yet when the very * first tc is created. */ return tc; }
/* Initializes a new thread context. Note that this doesn't set up a * thread itself, it just creates the data structure that exists in * MoarVM per thread. */ MVMThreadContext * MVM_tc_create(MVMThreadContext *parent, MVMInstance *instance) { MVMThreadContext *tc = MVM_calloc(1, sizeof(MVMThreadContext)); /* Associate with VM instance. */ tc->instance = instance; /* Use default loop for main thread; create a new one for others. */ if (instance->main_thread) { int r; tc->loop = MVM_calloc(1, sizeof(uv_loop_t)); r = uv_loop_init(tc->loop); if (r < 0) { MVM_free(tc->loop); MVM_free(tc); MVM_exception_throw_adhoc(parent, "Could not create a new Thread: %s", uv_strerror(r)); } } else { tc->loop = uv_default_loop(); } /* Set up GC nursery. We only allocate tospace initially, and allocate * fromspace the first time this thread GCs, provided it ever does. */ tc->nursery_tospace = MVM_calloc(1, MVM_NURSERY_SIZE); tc->nursery_alloc = tc->nursery_tospace; tc->nursery_alloc_limit = (char *)tc->nursery_alloc + MVM_NURSERY_SIZE; /* Set up temporary root handling. */ tc->num_temproots = 0; tc->alloc_temproots = MVM_TEMP_ROOT_BASE_ALLOC; tc->temproots = MVM_malloc(sizeof(MVMCollectable **) * tc->alloc_temproots); /* Set up intergenerational root handling. */ tc->num_gen2roots = 0; tc->alloc_gen2roots = 64; tc->gen2roots = MVM_malloc(sizeof(MVMCollectable *) * tc->alloc_gen2roots); /* Set up the second generation allocator. */ tc->gen2 = MVM_gc_gen2_create(instance); /* Allocate an initial call stack region for the thread. */ MVM_callstack_region_init(tc); /* Initialize random number generator state. */ MVM_proc_seed(tc, (MVM_platform_now() / 10000) * MVM_proc_getpid(tc)); /* Initialize frame sequence numbers */ tc->next_frame_nr = 0; tc->current_frame_nr = 0; /* Initialize last_payload, so we can be sure it's never NULL and don't * need to check. */ tc->last_payload = instance->VMNull; return tc; }
/* Initializes a new thread context. Note that this doesn't set up a * thread itself, it just creates the data structure that exists in * MoarVM per thread. */ MVMThreadContext * MVM_tc_create(MVMInstance *instance) { MVMThreadContext *tc = calloc(1, sizeof(MVMThreadContext)); /* Associate with VM instance. */ tc->instance = instance; /* Set up GC nursery. */ tc->nursery_fromspace = calloc(1, MVM_NURSERY_SIZE); tc->nursery_tospace = calloc(1, MVM_NURSERY_SIZE); tc->nursery_alloc = tc->nursery_tospace; tc->nursery_alloc_limit = (char *)tc->nursery_alloc + MVM_NURSERY_SIZE; /* Set up temporary root handling. */ tc->num_temproots = 0; tc->alloc_temproots = 16; tc->temproots = malloc(sizeof(MVMCollectable **) * tc->alloc_temproots); /* Set up intergenerational root handling. */ tc->num_gen2roots = 0; tc->alloc_gen2roots = 64; tc->gen2roots = malloc(sizeof(MVMCollectable *) * tc->alloc_gen2roots); /* Set up the second generation allocator. */ tc->gen2 = MVM_gc_gen2_create(instance); /* Set up table of per-static-frame chains. */ /* XXX For non-first threads, make them start with the size of the main thread's table. or, look into lazily initializing this. */ tc->frame_pool_table_size = MVMInitialFramePoolTableSize; tc->frame_pool_table = calloc(MVMInitialFramePoolTableSize, sizeof(MVMFrame *)); tc->loop = instance->default_loop ? uv_loop_new() : uv_default_loop(); /* Create a CallCapture for usecapture instructions in this thread (needs * special handling in initial thread as this runs before bootstrap). */ if (instance->CallCapture) tc->cur_usecapture = MVM_repr_alloc_init(tc, instance->CallCapture); /* Initialize random number generator state. */ MVM_proc_seed(tc, (MVM_platform_now() / 10000) * MVM_proc_getpid(tc)); #if MVM_HLL_PROFILE_CALLS #define PROFILE_INITIAL_SIZE (1 << 29) tc->profile_data_size = PROFILE_INITIAL_SIZE; tc->profile_data = malloc(sizeof(MVMProfileRecord) * PROFILE_INITIAL_SIZE); tc->profile_index = 0; #endif return tc; }