MVMObject * MVM_proc_getenvhash(MVMThreadContext *tc) { MVMInstance * const instance = tc->instance; MVMObject * env_hash; #ifdef _WIN32 const MVMuint16 acp = GetACP(); /* We should get ACP at runtime. */ #endif MVMuint32 pos = 0; MVMString *needle = MVM_string_ascii_decode(tc, instance->VMString, STR_WITH_LEN("=")); char *env; MVM_gc_root_temp_push(tc, (MVMCollectable **)&needle); env_hash = MVM_repr_alloc_init(tc, MVM_hll_current(tc)->slurpy_hash_type); MVM_gc_root_temp_push(tc, (MVMCollectable **)&env_hash); while ((env = environ[pos++]) != NULL) { #ifndef _WIN32 MVMString *str = MVM_string_utf8_c8_decode(tc, instance->VMString, env, strlen(env)); #else char * const _env = ANSIToUTF8(acp, env); MVMString *str = MVM_string_utf8_c8_decode(tc, instance->VMString, _env, strlen(_env)); #endif MVMuint32 index = MVM_string_index(tc, str, needle, 0); MVMString *key, *val; MVMObject *box; #ifdef _WIN32 MVM_free(_env); #endif MVM_gc_root_temp_push(tc, (MVMCollectable **)&str); key = MVM_string_substring(tc, str, 0, index); MVM_gc_root_temp_push(tc, (MVMCollectable **)&key); val = MVM_string_substring(tc, str, index + 1, -1); box = MVM_repr_box_str(tc, MVM_hll_current(tc)->str_box_type, val); MVM_repr_bind_key_o(tc, env_hash, key, box); MVM_gc_root_temp_pop_n(tc, 2); } MVM_gc_root_temp_pop_n(tc, 2); return env_hash; }
/* Loads bytecode from the specified file name and runs it. */ void MVM_vm_run_file(MVMInstance *instance, const char *filename) { /* Map the compilation unit into memory and dissect it. */ MVMThreadContext *tc = instance->main_thread; MVMCompUnit *cu = MVM_cu_map_from_file(tc, filename); MVMROOT(tc, cu, { /* The call to MVM_string_utf8_decode() may allocate, invalidating the location cu->body.filename */ MVMString *const str = MVM_string_utf8_c8_decode(tc, instance->VMString, filename, strlen(filename)); cu->body.filename = str; /* Run deserialization frame, if there is one. */ if (cu->body.deserialize_frame) { MVM_interp_run(tc, toplevel_initial_invoke, cu->body.deserialize_frame); } });
/* Reads a directory entry from a directory. */ MVMString * MVM_dir_read(MVMThreadContext *tc, MVMObject *oshandle) { MVMOSHandle *handle = get_dirhandle(tc, oshandle, "readdir"); MVMIODirIter *data = (MVMIODirIter *)handle->body.data; #ifdef _WIN32 MVMString *result; TCHAR dir[MAX_PATH]; WIN32_FIND_DATAW ffd; char *dir_str; if (data->dir_handle == INVALID_HANDLE_VALUE) { HANDLE hFind = FindFirstFileW(data->dir_name, &ffd); if (hFind == INVALID_HANDLE_VALUE) { MVM_exception_throw_adhoc(tc, "read from dirhandle failed: %d", GetLastError()); } data->dir_handle = hFind; dir_str = UnicodeToUTF8(ffd.cFileName); result = MVM_string_utf8_c8_decode(tc, tc->instance->VMString, dir_str, strlen(dir_str)); MVM_free(dir_str); return result; } else if (FindNextFileW(data->dir_handle, &ffd) != 0) { dir_str = UnicodeToUTF8(ffd.cFileName); result = MVM_string_decode(tc, tc->instance->VMString, dir_str, strlen(dir_str), data->encoding); MVM_free(dir_str); return result; } else { return tc->instance->str_consts.empty; } #else struct dirent entry; struct dirent *result; int ret; ret = readdir_r(data->dir_handle, &entry, &result); if (ret == 0) { if (result == NULL) return tc->instance->str_consts.empty; return MVM_string_decode(tc, tc->instance->VMString, entry.d_name, strlen(entry.d_name), data->encoding); } MVM_exception_throw_adhoc(tc, "Failed to read dirhandle: %d", errno); #endif }
/* Get the current working directory. */ MVMString * MVM_dir_cwd(MVMThreadContext *tc) { #ifdef _WIN32 char path[MAX_PATH]; size_t max_path = MAX_PATH; int r; #else char path[PATH_MAX]; size_t max_path = PATH_MAX; int r; #endif if ((r = uv_cwd(path, (size_t *)&max_path)) < 0) { MVM_exception_throw_adhoc(tc, "chdir failed: %s", uv_strerror(r)); } return MVM_string_utf8_c8_decode(tc, tc->instance->VMString, path, strlen(path)); }
/* Dumps a call graph node. */ static MVMObject * dump_call_graph_node(MVMThreadContext *tc, ProfDumpStrs *pds, const MVMProfileCallNode *pcn) { MVMObject *node_hash = new_hash(tc); MVMuint32 i; /* Let's see if we're dealing with a native call or a regular moar call */ if (pcn->sf) { /* Try to resolve the code filename and line number. */ MVMBytecodeAnnotation *annot = MVM_bytecode_resolve_annotation(tc, &(pcn->sf->body), 0); MVMint32 fshi = annot ? (MVMint32)annot->filename_string_heap_index : -1; /* Add name of code object. */ MVM_repr_bind_key_o(tc, node_hash, pds->name, box_s(tc, pcn->sf->body.name)); /* Add line number and file name. */ if (fshi >= 0 && fshi < pcn->sf->body.cu->body.num_strings) MVM_repr_bind_key_o(tc, node_hash, pds->file, box_s(tc, MVM_cu_string(tc, pcn->sf->body.cu, fshi))); else if (pcn->sf->body.cu->body.filename) MVM_repr_bind_key_o(tc, node_hash, pds->file, box_s(tc, pcn->sf->body.cu->body.filename)); else MVM_repr_bind_key_o(tc, node_hash, pds->file, box_s(tc, tc->instance->str_consts.empty)); MVM_repr_bind_key_o(tc, node_hash, pds->line, box_i(tc, annot ? (MVMint32)annot->line_number : -1)); MVM_free(annot); /* Use static frame memory address to get a unique ID. */ MVM_repr_bind_key_o(tc, node_hash, pds->id, box_i(tc, (MVMint64)pcn->sf)); } else { MVMString *function_name_string = MVM_string_utf8_c8_decode(tc, tc->instance->VMString, pcn->native_target_name, strlen(pcn->native_target_name)); MVM_repr_bind_key_o(tc, node_hash, pds->name, box_s(tc, function_name_string)); MVM_repr_bind_key_o(tc, node_hash, pds->file, box_s(tc, pds->native_lib)); MVM_repr_bind_key_o(tc, node_hash, pds->line, box_i(tc, -2)); /* Use the address of the name string as unique ID. a hack, but oh well. */ MVM_repr_bind_key_o(tc, node_hash, pds->id, box_i(tc, (MVMint64)pcn->native_target_name)); } /* Entry counts. */ if (pcn->total_entries) MVM_repr_bind_key_o(tc, node_hash, pds->entries, box_i(tc, pcn->total_entries)); if (pcn->specialized_entries) MVM_repr_bind_key_o(tc, node_hash, pds->spesh_entries, box_i(tc, pcn->specialized_entries)); if (pcn->jit_entries) MVM_repr_bind_key_o(tc, node_hash, pds->jit_entries, box_i(tc, pcn->jit_entries)); if (pcn->inlined_entries) MVM_repr_bind_key_o(tc, node_hash, pds->inlined_entries, box_i(tc, pcn->inlined_entries)); /* Total (inclusive) time. */ MVM_repr_bind_key_o(tc, node_hash, pds->inclusive_time, box_i(tc, pcn->total_time / 1000)); /* OSR and deopt counts. */ if (pcn->osr_count) MVM_repr_bind_key_o(tc, node_hash, pds->osr, box_i(tc, pcn->osr_count)); if (pcn->deopt_one_count) MVM_repr_bind_key_o(tc, node_hash, pds->deopt_one, box_i(tc, pcn->deopt_one_count)); if (pcn->deopt_all_count) MVM_repr_bind_key_o(tc, node_hash, pds->deopt_all, box_i(tc, pcn->deopt_all_count)); /* Visit successors in the call graph, dumping them and working out the * exclusive time. */ if (pcn->num_succ) { MVMObject *callees = new_array(tc); MVMuint64 exclusive_time = pcn->total_time; for (i = 0; i < pcn->num_succ; i++) { MVM_repr_push_o(tc, callees, dump_call_graph_node(tc, pds, pcn->succ[i])); exclusive_time -= pcn->succ[i]->total_time; } MVM_repr_bind_key_o(tc, node_hash, pds->exclusive_time, box_i(tc, exclusive_time / 1000)); MVM_repr_bind_key_o(tc, node_hash, pds->callees, callees); } else { MVM_repr_bind_key_o(tc, node_hash, pds->exclusive_time, box_i(tc, pcn->total_time / 1000)); } if (pcn->num_alloc) { /* Emit allocations. */ MVMObject *alloc_list = new_array(tc); MVM_repr_bind_key_o(tc, node_hash, pds->allocations, alloc_list); for (i = 0; i < pcn->num_alloc; i++) { MVMObject *alloc_info = new_hash(tc); MVMProfileAllocationCount *alloc = &pcn->alloc[i]; MVMObject *type = pcn->alloc[i].type; MVM_repr_bind_key_o(tc, alloc_info, pds->id, box_i(tc, (MVMint64)type)); MVM_repr_bind_key_o(tc, alloc_info, pds->type, type); if (alloc->allocations_spesh) MVM_repr_bind_key_o(tc, alloc_info, pds->spesh, box_i(tc, alloc->allocations_spesh)); if (alloc->allocations_jit) MVM_repr_bind_key_o(tc, alloc_info, pds->jit, box_i(tc, alloc->allocations_jit)); MVM_repr_bind_key_o(tc, alloc_info, pds->count, box_i(tc, alloc->allocations_interp + alloc->allocations_spesh + alloc->allocations_jit)); MVM_repr_push_o(tc, alloc_list, alloc_info); } } return node_hash; }