/* 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; }
/* 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; }