Example #1
0
File: moar.c Project: leedo/MoarVM
/* Create a new instance of the VM. */
MVMInstance * MVM_vm_create_instance(void) {
    MVMInstance *instance;
    char *spesh_log, *spesh_disable, *spesh_inline_disable, *spesh_osr_disable;
    char *jit_log, *jit_disable, *jit_bytecode_dir;
    char *dynvar_log;
    int init_stat;

    /* Set up instance data structure. */
    instance = calloc(1, sizeof(MVMInstance));

    /* Create the main thread's ThreadContext and stash it. */
    instance->main_thread = MVM_tc_create(instance);
    instance->main_thread->thread_id = 1;

    /* No user threads when we start, and next thread to be created gets ID 2
     * (the main thread got ID 1). */
    instance->num_user_threads    = 0;
    MVM_store(&instance->next_user_thread_id, 2);

    /* Set up the permanent roots storage. */
    instance->num_permroots   = 0;
    instance->alloc_permroots = 16;
    instance->permroots       = MVM_malloc(sizeof(MVMCollectable **) * instance->alloc_permroots);
    init_mutex(instance->mutex_permroots, "permanent roots");

    /* Create fixed size allocator. */
    instance->fsa = MVM_fixed_size_create(instance->main_thread);

    /* Set up REPR registry mutex. */
    init_mutex(instance->mutex_repr_registry, "REPR registry");

    /* Set up HLL config mutex. */
    init_mutex(instance->mutex_hllconfigs, "hll configs");

    /* Set up DLL registry mutex. */
    init_mutex(instance->mutex_dll_registry, "REPR registry");

    /* Set up extension registry mutex. */
    init_mutex(instance->mutex_ext_registry, "extension registry");

    /* Set up extension op registry mutex. */
    init_mutex(instance->mutex_extop_registry, "extension op registry");

    /* Set up weak reference hash mutex. */
    init_mutex(instance->mutex_sc_weakhash, "sc weakhash");

    /* Set up loaded compunits hash mutex. */
    init_mutex(instance->mutex_loaded_compunits, "loaded compunits");

    /* Set up container registry mutex. */
    init_mutex(instance->mutex_container_registry, "container registry");

    /* Set up persistent object ID hash mutex. */
    init_mutex(instance->mutex_object_ids, "object ID hash");

    /* Allocate all things during following setup steps directly in gen2, as
     * they will have program lifetime. */
    MVM_gc_allocate_gen2_default_set(instance->main_thread);

    init_mutex(instance->mutex_int_const_cache, "int constant cache");
    instance->int_const_cache = calloc(1, sizeof(MVMIntConstCache));

    /* Bootstrap 6model. It is assumed the GC will not be called during this. */
    MVM_6model_bootstrap(instance->main_thread);

    /* Fix up main thread's usecapture. */
    instance->main_thread->cur_usecapture = MVM_repr_alloc_init(instance->main_thread, instance->CallCapture);

    /* Initialize event loop thread starting mutex. */
    init_mutex(instance->mutex_event_loop_start, "event loop thread start");
    
    /* Create main thread object, and also make it the start of the all threads
     * linked list. */
    MVM_store(&instance->threads,
        (instance->main_thread->thread_obj = (MVMThread *)
            REPR(instance->boot_types.BOOTThread)->allocate(
                instance->main_thread, STABLE(instance->boot_types.BOOTThread))));
    instance->threads->body.stage = MVM_thread_stage_started;
    instance->threads->body.tc = instance->main_thread;
    instance->threads->body.thread_id = uv_thread_self();

    /* Create compiler registry */
    instance->compiler_registry = MVM_repr_alloc_init(instance->main_thread, instance->boot_types.BOOTHash);

    /* Set up compiler registr mutex. */
    init_mutex(instance->mutex_compiler_registry, "compiler registry");

    /* Create hll symbol tables */
    instance->hll_syms = MVM_repr_alloc_init(instance->main_thread, instance->boot_types.BOOTHash);

    /* Set up hll symbol tables mutex. */
    init_mutex(instance->mutex_hll_syms, "hll syms");

    /* Initialize string cclass handling. */
    MVM_string_cclass_init(instance->main_thread);

    /* Create callsite intern pool. */
    instance->callsite_interns = calloc(1, sizeof(MVMCallsiteInterns));
    init_mutex(instance->mutex_callsite_interns, "callsite interns");

    /* Allocate int to str cache. */
    instance->int_to_str_cache = calloc(MVM_INT_TO_STR_CACHE_SIZE, sizeof(MVMString *));

    /* Mutex for spesh installations, and check if we've a file we
     * should log specializations to. */
    init_mutex(instance->mutex_spesh_install, "spesh installations");
    spesh_log = getenv("MVM_SPESH_LOG");
    if (spesh_log && strlen(spesh_log))
        instance->spesh_log_fh = fopen(spesh_log, "w");
    spesh_disable = getenv("MVM_SPESH_DISABLE");
    if (!spesh_disable || strlen(spesh_disable) == 0) {
        instance->spesh_enabled = 1;
        spesh_inline_disable = getenv("MVM_SPESH_INLINE_DISABLE");
        if (!spesh_inline_disable || strlen(spesh_inline_disable) == 0)
            instance->spesh_inline_enabled = 1;
        spesh_osr_disable = getenv("MVM_SPESH_OSR_DISABLE");
        if (!spesh_osr_disable || strlen(spesh_osr_disable) == 0)
            instance->spesh_osr_enabled = 1;
    }

    jit_disable = getenv("MVM_JIT_DISABLE");
    if (!jit_disable || strlen(jit_disable) == 0)
        instance->jit_enabled = 1;
    jit_log = getenv("MVM_JIT_LOG");
    if (jit_log && strlen(jit_log))
        instance->jit_log_fh = fopen(jit_log, "w");
    jit_bytecode_dir = getenv("MVM_JIT_BYTECODE_DIR");
    if (jit_bytecode_dir && strlen(jit_bytecode_dir))
        instance->jit_bytecode_dir = jit_bytecode_dir;
    dynvar_log = getenv("MVM_DYNVAR_LOG");
    if (dynvar_log && strlen(dynvar_log))
        instance->dynvar_log_fh = fopen(dynvar_log, "w");
    else
        instance->dynvar_log_fh = NULL;

    /* Create std[in/out/err]. */
    setup_std_handles(instance->main_thread);

    /* Current instrumentation level starts at 1; used to trigger all frames
     * to be verified before their first run. */
    instance->instrumentation_level = 1;

    /* Back to nursery allocation, now we're set up. */
    MVM_gc_allocate_gen2_default_clear(instance->main_thread);

    return instance;
}
Example #2
0
/* Create a new instance of the VM. */
MVMInstance * MVM_vm_create_instance(void) {
    MVMInstance *instance;
    char *spesh_log, *spesh_nodelay, *spesh_disable, *spesh_inline_disable, *spesh_osr_disable;
    char *jit_log, *jit_disable, *jit_bytecode_dir;
    char *dynvar_log;
    int init_stat;

    /* Set up instance data structure. */
    instance = MVM_calloc(1, sizeof(MVMInstance));

    /* Create the main thread's ThreadContext and stash it. */
    instance->main_thread = MVM_tc_create(instance);
    instance->main_thread->thread_id = 1;

    /* No user threads when we start, and next thread to be created gets ID 2
     * (the main thread got ID 1). */
    instance->num_user_threads    = 0;
    MVM_store(&instance->next_user_thread_id, 2);

    /* Set up the permanent roots storage. */
    instance->num_permroots         = 0;
    instance->alloc_permroots       = 16;
    instance->permroots             = MVM_malloc(sizeof(MVMCollectable **) * instance->alloc_permroots);
    instance->permroot_descriptions = MVM_malloc(sizeof(char *) * instance->alloc_permroots);
    init_mutex(instance->mutex_permroots, "permanent roots");

    /* Create fixed size allocator. */
    instance->fsa = MVM_fixed_size_create(instance->main_thread);

    /* Set up REPR registry mutex. */
    init_mutex(instance->mutex_repr_registry, "REPR registry");

    /* Set up HLL config mutex. */
    init_mutex(instance->mutex_hllconfigs, "hll configs");

    /* Set up DLL registry mutex. */
    init_mutex(instance->mutex_dll_registry, "REPR registry");

    /* Set up extension registry mutex. */
    init_mutex(instance->mutex_ext_registry, "extension registry");

    /* Set up extension op registry mutex. */
    init_mutex(instance->mutex_extop_registry, "extension op registry");

    /* Set up weak reference hash mutex. */
    init_mutex(instance->mutex_sc_weakhash, "sc weakhash");

    /* Set up loaded compunits hash mutex. */
    init_mutex(instance->mutex_loaded_compunits, "loaded compunits");

    /* Set up container registry mutex. */
    init_mutex(instance->mutex_container_registry, "container registry");

    /* Set up persistent object ID hash mutex. */
    init_mutex(instance->mutex_object_ids, "object ID hash");

    /* Allocate all things during following setup steps directly in gen2, as
     * they will have program lifetime. */
    MVM_gc_allocate_gen2_default_set(instance->main_thread);

    /* Set up integer constant and string cache. */
    init_mutex(instance->mutex_int_const_cache, "int constant cache");
    instance->int_const_cache = MVM_calloc(1, sizeof(MVMIntConstCache));
    instance->int_to_str_cache = MVM_calloc(MVM_INT_TO_STR_CACHE_SIZE, sizeof(MVMString *));

    /* Bootstrap 6model. It is assumed the GC will not be called during this. */
    MVM_6model_bootstrap(instance->main_thread);

    /* Fix up main thread's usecapture and last_payload. */
    instance->main_thread->cur_usecapture = MVM_repr_alloc_init(instance->main_thread, instance->CallCapture);
    instance->main_thread->last_payload = instance->VMNull;

    /* Initialize event loop thread starting mutex. */
    init_mutex(instance->mutex_event_loop_start, "event loop thread start");

    /* Create main thread object, and also make it the start of the all threads
     * linked list. */
    MVM_store(&instance->threads,
        (instance->main_thread->thread_obj = (MVMThread *)
            REPR(instance->boot_types.BOOTThread)->allocate(
                instance->main_thread, STABLE(instance->boot_types.BOOTThread))));
    instance->threads->body.stage = MVM_thread_stage_started;
    instance->threads->body.tc = instance->main_thread;
    instance->threads->body.native_thread_id = MVM_platform_thread_id();
    instance->threads->body.thread_id = instance->main_thread->thread_id;

    /* Create compiler registry */
    instance->compiler_registry = MVM_repr_alloc_init(instance->main_thread, instance->boot_types.BOOTHash);

    /* Set up compiler registr mutex. */
    init_mutex(instance->mutex_compiler_registry, "compiler registry");

    /* Create hll symbol tables */
    instance->hll_syms = MVM_repr_alloc_init(instance->main_thread, instance->boot_types.BOOTHash);

    /* Set up hll symbol tables mutex. */
    init_mutex(instance->mutex_hll_syms, "hll syms");

    /* Initialize Unicode database */
    MVM_unicode_init(instance->main_thread);

    /* Initialize string cclass handling. */
    MVM_string_cclass_init(instance->main_thread);

    /* Create callsite intern pool. */
    instance->callsite_interns = MVM_calloc(1, sizeof(MVMCallsiteInterns));
    init_mutex(instance->mutex_callsite_interns, "callsite interns");

    /* There's some callsites we statically use all over the place. Intern
     * them, so that spesh may end up optimizing more "internal" stuff. */
    MVM_callsite_initialize_common(instance->main_thread);

    /* Multi-cache additions mutex. */
    init_mutex(instance->mutex_multi_cache_add, "multi-cache addition");

    /* Current instrumentation level starts at 1; used to trigger all frames
     * to be verified before their first run. */
    instance->instrumentation_level = 1;

    /* Mutex for spesh installations, and check if we've a file we
     * should log specializations to. */
    init_mutex(instance->mutex_spesh_install, "spesh installations");
    spesh_log = getenv("MVM_SPESH_LOG");
    if (spesh_log && strlen(spesh_log))
        instance->spesh_log_fh = fopen_perhaps_with_pid(spesh_log, "w");
    spesh_disable = getenv("MVM_SPESH_DISABLE");
    if (!spesh_disable || strlen(spesh_disable) == 0) {
        instance->spesh_enabled = 1;
        spesh_inline_disable = getenv("MVM_SPESH_INLINE_DISABLE");
        if (!spesh_inline_disable || strlen(spesh_inline_disable) == 0)
            instance->spesh_inline_enabled = 1;
        spesh_osr_disable = getenv("MVM_SPESH_OSR_DISABLE");
        if (!spesh_osr_disable || strlen(spesh_osr_disable) == 0)
            instance->spesh_osr_enabled = 1;
    }

    /* Should we specialize without warm up delays? Used to find bugs in the
     * specializer and JIT. */
    spesh_nodelay = getenv("MVM_SPESH_NODELAY");
    if (spesh_nodelay && strlen(spesh_nodelay)) {
        instance->spesh_nodelay = 1;
    }

    /* JIT environment/logging setup. */
    jit_disable = getenv("MVM_JIT_DISABLE");
    if (!jit_disable || strlen(jit_disable) == 0)
        instance->jit_enabled = 1;
    jit_log = getenv("MVM_JIT_LOG");
    if (jit_log && strlen(jit_log))
        instance->jit_log_fh = fopen_perhaps_with_pid(jit_log, "w");
    jit_bytecode_dir = getenv("MVM_JIT_BYTECODE_DIR");
    if (jit_bytecode_dir && strlen(jit_bytecode_dir)) {
        char *bytecode_map_name = MVM_malloc(strlen(jit_bytecode_dir) + strlen("/jit-map.txt") + 1);
        sprintf(bytecode_map_name, "%s/jit-map.txt", jit_bytecode_dir);
        instance->jit_bytecode_map = fopen(bytecode_map_name, "w");
        instance->jit_bytecode_dir = jit_bytecode_dir;
        MVM_free(bytecode_map_name);
    }
    instance->jit_seq_nr = 0;

    /* Various kinds of debugging that can be enabled. */
    dynvar_log = getenv("MVM_DYNVAR_LOG");
    if (dynvar_log && strlen(dynvar_log)) {
        instance->dynvar_log_fh = fopen_perhaps_with_pid(dynvar_log, "w");
        fprintf(instance->dynvar_log_fh, "+ x 0 0 0 0 0 %llu\n", uv_hrtime());
        fflush(instance->dynvar_log_fh);
        instance->dynvar_log_lasttime = uv_hrtime();
    }
    else
        instance->dynvar_log_fh = NULL;
    instance->nfa_debug_enabled = getenv("MVM_NFA_DEB") ? 1 : 0;
    if (getenv("MVM_CROSS_THREAD_WRITE_LOG")) {
        instance->cross_thread_write_logging = 1;
        instance->cross_thread_write_logging_include_locked =
            getenv("MVM_CROSS_THREAD_WRITE_LOG_INCLUDE_LOCKED") ? 1 : 0;
        instance->instrumentation_level++;
        init_mutex(instance->mutex_cross_thread_write_logging,
            "cross thread write logging output");
    }
    else {
        instance->cross_thread_write_logging = 0;
    }

    /* Set up NFG state mutation mutex. */
    instance->nfg = calloc(1, sizeof(MVMNFGState));
    init_mutex(instance->nfg->update_mutex, "NFG update mutex");

    /* Create std[in/out/err]. */
    setup_std_handles(instance->main_thread);

    /* Back to nursery allocation, now we're set up. */
    MVM_gc_allocate_gen2_default_clear(instance->main_thread);

    return instance;
}