Example #1
0
/* Takes a string and sets it up as a decode stream separator. */
void MVM_string_decode_stream_sep_from_strings(MVMThreadContext *tc, MVMDecodeStreamSeparators *sep_spec,
                                               MVMString **seps, MVMint32 num_seps) {
    MVMGraphemeIter gi;
    MVMint32 i, graph_length, graph_pos;

    if (num_seps > 0xFFF)
        MVM_exception_throw_adhoc(tc, "Too many line separators");

    MVM_free(sep_spec->sep_lengths);
    MVM_free(sep_spec->sep_graphemes);
    MVM_free(sep_spec->final_graphemes);

    sep_spec->num_seps = num_seps;
    sep_spec->sep_lengths = MVM_malloc(num_seps * sizeof(MVMint32));
    graph_length = 0;
    for (i = 0; i < num_seps; i++) {
        MVMuint32 num_graphs = MVM_string_graphs(tc, seps[i]);
        if (num_graphs > 0xFFFF)
            MVM_exception_throw_adhoc(tc, "Line separator too long");
        sep_spec->sep_lengths[i] = num_graphs;
        graph_length += num_graphs;
    }

    sep_spec->sep_graphemes = MVM_malloc(graph_length * sizeof(MVMGrapheme32));
    graph_pos = 0;
    for (i = 0; i < num_seps; i++) {
        MVM_string_gi_init(tc, &gi, seps[i]);
        while (MVM_string_gi_has_more(tc, &gi))
            sep_spec->sep_graphemes[graph_pos++] = MVM_string_gi_get_grapheme(tc, &gi);
    }

    cache_sep_info(tc, sep_spec);
}
Example #2
0
/* Throws away byte buffers no longer needed. */
void MVM_string_decodestream_discard_to(MVMThreadContext *tc, MVMDecodeStream *ds, const MVMDecodeStreamBytes *bytes, MVMint32 pos) {
    while (ds->bytes_head != bytes) {
        MVMDecodeStreamBytes *discard = ds->bytes_head;
        ds->abs_byte_pos += discard->length - ds->bytes_head_pos;
        ds->bytes_head = discard->next;
        ds->bytes_head_pos = 0;
        MVM_free(discard->bytes);
        MVM_free(discard);
    }
    if (!ds->bytes_head && pos == 0)
        return;
    if (ds->bytes_head->length == pos) {
        /* We ate all of the new head buffer too; also free it. */
        MVMDecodeStreamBytes *discard = ds->bytes_head;
        ds->abs_byte_pos += discard->length - ds->bytes_head_pos;
        ds->bytes_head = discard->next;
        ds->bytes_head_pos = 0;
        MVM_free(discard->bytes);
        MVM_free(discard);
        if (ds->bytes_head == NULL)
            ds->bytes_tail = NULL;
    }
    else {
        ds->abs_byte_pos += pos - ds->bytes_head_pos;
        ds->bytes_head_pos = pos;
    }
}
Example #3
0
/* Writes the specified string to the file handle, maybe with a newline. */
static MVMint64 write_str(MVMThreadContext *tc, MVMOSHandle *h, MVMString *str, MVMint64 newline) {
    MVMIOFileData *data = (MVMIOFileData *)h->body.data;
    MVMuint64 output_size;
    MVMint64 bytes_written;
    char *output = MVM_string_encode(tc, str, 0, -1, &output_size, data->encoding, NULL,
        MVM_TRANSLATE_NEWLINE_OUTPUT);
    uv_buf_t write_buf  = uv_buf_init(output, output_size);
    uv_fs_t req;

    bytes_written = uv_fs_write(tc->loop, &req, data->fd, &write_buf, 1, -1, NULL);
    if (bytes_written < 0) {
        MVM_free(output);
        MVM_exception_throw_adhoc(tc, "Failed to write bytes to filehandle: %s", uv_strerror(req.result));
    }
    MVM_free(output);

    if (newline) {
        uv_buf_t nl = uv_buf_init("\n", 1);
        if (uv_fs_write(tc->loop, &req, data->fd, &nl, 1, -1, NULL) < 0)
            MVM_exception_throw_adhoc(tc, "Failed to write newline to filehandle: %s", uv_strerror(req.result));
        bytes_written++;
    }

    return bytes_written;
}
Example #4
0
/* Copies up to the requested number of bytes into the supplied buffer, and
 * returns the number of bytes we actually copied. Takes from from the start
 * of the stream. */
MVMint64 MVM_string_decodestream_bytes_to_buf(MVMThreadContext *tc, MVMDecodeStream *ds, char **buf, MVMint32 bytes) {
    MVMint32 taken = 0;
    *buf = NULL;
    while (taken < bytes && ds->bytes_head) {
        /* Take what we can. */
        MVMDecodeStreamBytes *cur_bytes = ds->bytes_head;
        MVMint32 required  = bytes - taken;
        MVMint32 available = cur_bytes->length - ds->bytes_head_pos;
        if (available <= required) {
            /* Take everything in this buffer and remove it. */
            if (!*buf)
                *buf = MVM_malloc(cur_bytes->next ? bytes : available);
            memcpy(*buf + taken, cur_bytes->bytes + ds->bytes_head_pos, available);
            taken += available;
            ds->bytes_head = cur_bytes->next;
            ds->bytes_head_pos = 0;
            MVM_free(cur_bytes->bytes);
            MVM_free(cur_bytes);
        }
        else {
            /* Just take what we need. */
            if (!*buf)
                *buf = MVM_malloc(required);
            memcpy(*buf + taken, cur_bytes->bytes + ds->bytes_head_pos, required);
            taken += required;
            ds->bytes_head_pos += required;
        }
    }
    if (ds->bytes_head == NULL)
        ds->bytes_tail = NULL;
    ds->abs_byte_pos += taken;
    return taken;
}
Example #5
0
/* Opens a file, returning a synchronous file handle. */
MVMObject * MVM_file_open_fh(MVMThreadContext *tc, MVMString *filename, MVMString *mode) {
    char          * const fname  = MVM_string_utf8_c8_encode_C_string(tc, filename);
    char          * const fmode  = MVM_string_utf8_encode_C_string(tc, mode);
    MVMOSHandle   * const result = (MVMOSHandle *)MVM_repr_alloc_init(tc, tc->instance->boot_types.BOOTIO);
    MVMIOFileData * const data   = MVM_calloc(1, sizeof(MVMIOFileData));
    uv_fs_t req;
    uv_file fd;

    /* Resolve mode description to flags. */
    int flag;
    if (!resolve_open_mode(&flag, fmode)) {
        char *waste[] = { fmode, NULL };
        MVM_free(fname);
        MVM_exception_throw_adhoc_free(tc, waste, "Invalid open mode: %s", fmode);
    }
    MVM_free(fmode);

    /* Try to open the file. */
    if ((fd = uv_fs_open(tc->loop, &req, (const char *)fname, flag, DEFAULT_MODE, NULL)) < 0) {
        char *waste[] = { fname, NULL };
        MVM_exception_throw_adhoc_free(tc, waste, "Failed to open file %s: %s", fname, uv_strerror(req.result));
    }

    /* Set up handle. */
    data->fd          = fd;
    data->filename    = fname;
    data->encoding    = MVM_encoding_type_utf8;
    MVM_string_decode_stream_sep_default(tc, &(data->sep_spec));
    result->body.ops  = &op_table;
    result->body.data = data;

    return (MVMObject *)result;
}
Example #6
0
/* Adds a static frame table index reference to the collectable snapshot entry,
 * either using an existing table entry or adding a new one. */
static void set_static_frame_index(MVMThreadContext *tc, MVMHeapSnapshotState *ss,
       MVMHeapSnapshotCollectable *col, MVMStaticFrame *sf) {
    MVMuint64 name_idx = get_vm_string_index(tc, ss, sf->body.name);
    MVMuint64 cuid_idx = get_vm_string_index(tc, ss, sf->body.cuuid);

    MVMCompUnit *cu = sf->body.cu;
    MVMBytecodeAnnotation *ann = MVM_bytecode_resolve_annotation(tc, &(sf->body), 0);
    MVMuint64 line = ann ? ann->line_number : 1;
    MVMuint64 file_idx = ann && ann->filename_string_heap_index < cu->body.num_strings
        ? get_vm_string_index(tc, ss, MVM_cu_string(tc, cu, ann->filename_string_heap_index))
        : get_vm_string_index(tc, ss, cu->body.filename);

    MVMuint64 i;
    MVMHeapSnapshotStaticFrame *s;
    for (i = 0; i < ss->col->num_static_frames; i++) {
        s = &(ss->col->static_frames[i]);
        if (s->name == name_idx && s->cuid == cuid_idx && s->line == line && s->file == file_idx) {
            col->type_or_frame_index = i;
            MVM_free(ann);
            return;
        }
    }

    MVM_free(ann);

    grow_storage(&(ss->col->static_frames), &(ss->col->num_static_frames),
        &(ss->col->alloc_static_frames), sizeof(MVMHeapSnapshotStaticFrame));
    s = &(ss->col->static_frames[ss->col->num_static_frames]);
    s->name = name_idx;
    s->cuid = cuid_idx;
    s->line = line;
    s->file = file_idx;
    col->type_or_frame_index = ss->col->num_static_frames;
    ss->col->num_static_frames++;
}
Example #7
0
/* Cleans up reader state. */
static void cleanup_all(MVMThreadContext *tc, ReaderState *rs) {
    if (rs->frame_outer_fixups) {
        MVM_free(rs->frame_outer_fixups);
        rs->frame_outer_fixups = NULL;
    }
    MVM_free(rs);
}
Example #8
0
MVMint64 MVM_io_syncstream_write_str(MVMThreadContext *tc, MVMOSHandle *h, MVMString *str, MVMint64 newline) {
    MVMIOSyncStreamData *data = (MVMIOSyncStreamData *)h->body.data;
    char *output;
    MVMuint64 output_size;
    uv_write_t *req;
    uv_buf_t write_buf;
    int r;

    output = MVM_string_encode(tc, str, 0, -1, &output_size, data->encoding);
    if (newline) {
        output = (char *)MVM_realloc(output, ++output_size);
        output[output_size - 1] = '\n';
    }
    req = MVM_malloc(sizeof(uv_write_t));
    write_buf = uv_buf_init(output, output_size);
    uv_ref((uv_handle_t *)data->handle);
    if ((r = uv_write(req, data->handle, &write_buf, 1, write_cb)) < 0) {
        uv_unref((uv_handle_t *)data->handle);
        MVM_free(req);
        MVM_free(output);
        MVM_exception_throw_adhoc(tc, "Failed to write string to stream: %s", uv_strerror(r));
    }
    else {
        uv_run(tc->loop, UV_RUN_DEFAULT);
        MVM_free(output);
    }

    data->total_bytes_written += output_size;
    return output_size;
}
Example #9
0
/* Establishes a connection. */
static void socket_connect(MVMThreadContext *tc, MVMOSHandle *h, MVMString *host, MVMint64 port) {
    MVMIOSyncSocketData *data = (MVMIOSyncSocketData *)h->body.data;
    unsigned int interval_id;

    interval_id = MVM_telemetry_interval_start(tc, "syncsocket connect");
    if (!data->handle) {
        struct sockaddr *dest = MVM_io_resolve_host_name(tc, host, port);
        int r;

        Socket s = socket(dest->sa_family , SOCK_STREAM , 0);
        if (MVM_IS_SOCKET_ERROR(s)) {
            MVM_free(dest);
            MVM_telemetry_interval_stop(tc, interval_id, "syncsocket connect");
            throw_error(tc, s, "create socket");
        }

        do {
            MVM_gc_mark_thread_blocked(tc);
            r = connect(s, dest, (socklen_t)get_struct_size_for_family(dest->sa_family));
            MVM_gc_mark_thread_unblocked(tc);
        } while(r == -1 && errno == EINTR);
        MVM_free(dest);
        if (MVM_IS_SOCKET_ERROR(r)) {
            MVM_telemetry_interval_stop(tc, interval_id, "syncsocket connect");
            throw_error(tc, s, "connect socket");
        }

        data->handle = s;
    }
    else {
        MVM_telemetry_interval_stop(tc, interval_id, "syncsocket didn't connect");
        MVM_exception_throw_adhoc(tc, "Socket is already bound or connected");
    }
}
Example #10
0
File: log.c Project: Revlin/MoarVM
static char * jitcode_name(MVMThreadContext *tc, MVMJitCode *code) {
    MVMuint64 cuuid_len;
    MVMuint64 name_len;
    MVMuint8 *cuuid = MVM_string_ascii_encode(tc, code->sf->body.cuuid,
                                              &cuuid_len);
    MVMuint8 *name  = MVM_string_ascii_encode(tc, code->sf->body.name,
                                              &name_len);
    MVMuint64 dirname_len = strlen(tc->instance->jit_bytecode_dir);
    // 4 chars for prefix, 3 chars for the separators, 4 for the postfix, 1 for the 0
    char *filename = MVM_malloc(dirname_len + name_len + cuuid_len + 12);
    char *dst = filename;
    memcpy(dst, tc->instance->jit_bytecode_dir, dirname_len);
    dst[dirname_len] = '/';
    dst += dirname_len + 1;
    memcpy(dst, "jit-", 4);
    dst += 4;
    memcpy(dst, cuuid, cuuid_len);
    dst[cuuid_len] = '.';
    dst += cuuid_len + 1;
    memcpy(dst, name, name_len);
    dst += name_len;
    memcpy(dst, ".bin", 5);
    MVM_free(name);
    MVM_free(cuuid);
    return filename;
}
Example #11
0
/* Dumps the statistics associated with a particular callsite object. */
void dump_stats_by_callsite(MVMThreadContext *tc, DumpStr *ds, MVMSpeshStatsByCallsite *css) {
    MVMuint32 i, j, k;

    if (css->cs)
        dump_callsite(tc, ds, css->cs);
    else
        append(ds, "No interned callsite\n");
    appendf(ds, "    Callsite hits: %d\n\n", css->hits);
    if (css->osr_hits)
        appendf(ds, "    OSR hits: %d\n\n", css->osr_hits);
    appendf(ds, "    Maximum stack depth: %d\n\n", css->max_depth);

    for (i = 0; i < css->num_by_type; i++) {
        MVMSpeshStatsByType *tss = &(css->by_type[i]);
        appendf(ds, "    Type tuple %d\n", i);
        dump_stats_type_tuple(tc, ds, css->cs, tss->arg_types, "        ");
        appendf(ds, "        Hits: %d\n", tss->hits);
        if (tss->osr_hits)
            appendf(ds, "        OSR hits: %d\n", tss->osr_hits);
        appendf(ds, "        Maximum stack depth: %d\n", tss->max_depth);
        if (tss->num_by_offset) {
            append(ds, "        Logged at offset:\n");
            for (j = 0; j < tss->num_by_offset; j++) {
                MVMSpeshStatsByOffset *oss = &(tss->by_offset[j]);
                appendf(ds, "            %d:\n", oss->bytecode_offset);
                for (k = 0; k < oss->num_types; k++)
                    appendf(ds, "                %d x type %s (%s)\n",
                        oss->types[k].count,
                        MVM_6model_get_stable_debug_name(tc, oss->types[k].type->st),
                        (oss->types[k].type_concrete ? "Conc" : "TypeObj"));
                for (k = 0; k < oss->num_invokes; k++) {
                    char *body_name = MVM_string_utf8_encode_C_string(tc, oss->invokes[k].sf->body.name);
                    char *body_cuuid = MVM_string_utf8_encode_C_string(tc, oss->invokes[k].sf->body.cuuid);
                    appendf(ds,
                        "                %d x static frame '%s' (%s) (caller is outer: %d, multi %d)\n",
                        oss->invokes[k].count,
                        body_name,
                        body_cuuid,
                        oss->invokes[k].caller_is_outer_count,
                        oss->invokes[k].was_multi_count);
                    MVM_free(body_name);
                    MVM_free(body_cuuid);
                }
                for (k = 0; k < oss->num_type_tuples; k++) {
                    appendf(ds, "                %d x type tuple:\n",
                        oss->type_tuples[k].count);
                    dump_stats_type_tuple(tc, ds, oss->type_tuples[k].cs,
                        oss->type_tuples[k].arg_types,
                        "                    ");
                }
                for (k = 0; k < oss->num_plugin_guards; k++)
                    appendf(ds, "                %d x spesh plugin guard index %d\n",
                        oss->plugin_guards[k].count,
                        oss->plugin_guards[k].guard_index);
            }
        }
        append(ds, "\n");
    }
}
Example #12
0
/* This function may return any type of sockaddr e.g. sockaddr_un, sockaddr_in or sockaddr_in6
 * It shouldn't be a problem with general code as long as the port number is kept below the int16 limit: 65536
 * After this it defines the family which may spawn non internet sockaddr's
 * The family can be extracted by (port >> 16) & USHORT_MAX
 *
 * Currently supported families:
 *
 * AF_UNSPEC = 1
 *   Unspecified, in most cases should be equal to AF_INET or AF_INET6
 *
 * AF_UNIX = 1
 *   Unix domain socket, will spawn a sockaddr_un which will use the given host as path
 *   e.g: MVM_io_resolve_host_name(tc, "/run/moarvm.sock", 1 << 16)
 *   will spawn an unix domain socket on /run/moarvm.sock
 *
 * AF_INET = 2
 *   IPv4 socket
 *
 * AF_INET6 = 10
 *   IPv6 socket
 */
struct sockaddr * MVM_io_resolve_host_name(MVMThreadContext *tc, MVMString *host, MVMint64 port) {
    char *host_cstr = MVM_string_utf8_encode_C_string(tc, host);
    struct sockaddr *dest;
    int error;
    struct addrinfo *result;
    char port_cstr[8];
    unsigned short family = (port >> 16) & USHRT_MAX;
    struct addrinfo hints;

#ifndef _WIN32
    /* AF_UNIX = 1 */
    if (family == AF_UNIX) {
        struct sockaddr_un *result_un = MVM_malloc(sizeof(struct sockaddr_un));

        if (strlen(host_cstr) > 107) {
            MVM_free(result_un);
            MVM_free(host_cstr);
            MVM_exception_throw_adhoc(tc, "Socket path can only be maximal 107 characters long");
        }

        result_un->sun_family = AF_UNIX;
        strcpy(result_un->sun_path, host_cstr);
        MVM_free(host_cstr);

        return (struct sockaddr *)result_un;
    }
#endif

    hints.ai_family = family;
    hints.ai_socktype = 0;
    hints.ai_flags = AI_PASSIVE;
    hints.ai_protocol = 0;
    hints.ai_addrlen = 0;
    hints.ai_addr = NULL;
    hints.ai_canonname = NULL;
    hints.ai_next = NULL;

    snprintf(port_cstr, 8, "%d", (int)port);

    MVM_gc_mark_thread_blocked(tc);
    error = getaddrinfo(host_cstr, port_cstr, &hints, &result);
    MVM_gc_mark_thread_unblocked(tc);
    if (error == 0) {
        size_t size = get_struct_size_for_family(result->ai_addr->sa_family);
        MVM_free(host_cstr);
        dest = MVM_malloc(size);
        memcpy(dest, result->ai_addr, size);
    }
    else {
        char *waste[] = { host_cstr, NULL };
        MVM_exception_throw_adhoc_free(tc, waste, "Failed to resolve host name '%s' with family %d. Error: '%s'",
                                       host_cstr, family, gai_strerror(error));
    }
    freeaddrinfo(result);

    return dest;
}
Example #13
0
/* 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;
}
Example #14
0
static MVMString * take_chars(MVMThreadContext *tc, MVMDecodeStream *ds, MVMint32 chars, MVMint32 exclude) {
    MVMString *result;
    MVMint32   found = 0;
    MVMint32   result_found = 0;

    MVMint32   result_chars = chars - exclude;
    if (result_chars < 0)
        MVM_exception_throw_adhoc(tc, "DecodeStream take_chars: chars - exclude < 0 should never happen");

    result                       = (MVMString *)MVM_repr_alloc_init(tc, tc->instance->VMString);
    result->body.storage.blob_32 = MVM_malloc(result_chars * sizeof(MVMGrapheme32));
    result->body.storage_type    = MVM_STRING_GRAPHEME_32;
    result->body.num_graphs      = result_chars;
    while (found < chars) {
        MVMDecodeStreamChars *cur_chars = ds->chars_head;
        MVMint32 available = cur_chars->length - ds->chars_head_pos;
        if (available <= chars - found) {
            /* We need all that's left in this buffer and likely
             * more. */
            MVMDecodeStreamChars *next_chars = cur_chars->next;
            if (available <= result_chars - result_found) {
                memcpy(result->body.storage.blob_32 + result_found,
                    cur_chars->chars + ds->chars_head_pos,
                    available * sizeof(MVMGrapheme32));
                result_found += available;
            }
            else {
                MVMint32 to_copy = result_chars - result_found;
                memcpy(result->body.storage.blob_32 + result_found,
                    cur_chars->chars + ds->chars_head_pos,
                    to_copy * sizeof(MVMGrapheme32));
                result_found += to_copy;
            }
            found += available;
            MVM_free(cur_chars->chars);
            MVM_free(cur_chars);
            ds->chars_head = next_chars;
            ds->chars_head_pos = 0;
            if (ds->chars_head == NULL)
                ds->chars_tail = NULL;
        }
        else {
            /* There's enough in this buffer to satisfy us, and we'll leave
             * some behind. */
            MVMint32 take = chars - found;
            MVMint32 to_copy = result_chars - result_found;
            memcpy(result->body.storage.blob_32 + result_found,
                cur_chars->chars + ds->chars_head_pos,
                to_copy * sizeof(MVMGrapheme32));
            result_found += to_copy;
            found += take;
            ds->chars_head_pos += take;
        }
    }
    return result;
}
Example #15
0
/* Change directory. */
void MVM_dir_chdir(MVMThreadContext *tc, MVMString *dir) {
    char * const dirstring = MVM_string_utf8_encode_C_string(tc, dir);

    if (uv_chdir((const char *)dirstring) != 0) {
        MVM_free(dirstring);
        MVM_exception_throw_adhoc(tc, "chdir failed: %s", uv_strerror(errno));
    }

    MVM_free(dirstring);
}
Example #16
0
/* Frees data associated with the handle. */
static void gc_free(MVMThreadContext *tc, MVMObject *h, void *d) {
    MVMIOFileData *data = (MVMIOFileData *)d;
    if (data) {
        if (data->ds)
            MVM_string_decodestream_destory(tc, data->ds);
        if (data->filename)
            MVM_free(data->filename);
        MVM_free(data);
    }
}
Example #17
0
/* Destroys a decoding stream, freeing all associated memory (including the
 * buffers). */
void MVM_string_decodestream_destory(MVMThreadContext *tc, MVMDecodeStream *ds) {
    MVMDecodeStreamBytes *cur_bytes = ds->bytes_head;
    while (cur_bytes) {
        MVMDecodeStreamBytes *next_bytes = cur_bytes->next;
        MVM_free(cur_bytes->bytes);
        MVM_free(cur_bytes);
        cur_bytes = next_bytes;
    }
    MVM_free(ds);
}
Example #18
0
/* Tries to intern the callsite, freeing and updating the one passed in and
 * replacing it with an already interned one if we find it. */
MVM_PUBLIC void MVM_callsite_try_intern(MVMThreadContext *tc, MVMCallsite **cs_ptr) {
    MVMCallsiteInterns *interns    = tc->instance->callsite_interns;
    MVMCallsite        *cs         = *cs_ptr;
    MVMint32            num_flags  = cs->flag_count;
    MVMint32            num_nameds = MVM_callsite_num_nameds(tc, cs);
    MVMint32 i, found;

    /* Can't intern anything with flattening. */
    if (cs->has_flattening)
        return;

    /* Also can't intern past the max arity. */
    if (num_flags >= MVM_INTERN_ARITY_LIMIT)
        return;

    /* Can intern things with nameds, provided we know the names. */
    if (num_nameds > 0 && !cs->arg_names)
        return;

    /* Obtain mutex protecting interns store. */
    uv_mutex_lock(&tc->instance->mutex_callsite_interns);

    /* Search for a match. */
    found = 0;
    for (i = 0; i < interns->num_by_arity[num_flags]; i++) {
        if (callsites_equal(tc, interns->by_arity[num_flags][i], cs, num_flags, num_nameds)) {
            /* Got a match! Free the one we were passed and replace it with
             * the interned one. */
            if (num_flags)
                MVM_free(cs->arg_flags);
            MVM_free(cs->arg_names);
            MVM_free(cs);
            *cs_ptr = interns->by_arity[num_flags][i];
            found = 1;
            break;
        }
    }

    /* If it wasn't found, store it for the future. */
    if (!found) {
        if (interns->num_by_arity[num_flags] % 8 == 0) {
            if (interns->num_by_arity[num_flags])
                interns->by_arity[num_flags] = MVM_realloc(
                    interns->by_arity[num_flags],
                    sizeof(MVMCallsite *) * (interns->num_by_arity[num_flags] + 8));
            else
                interns->by_arity[num_flags] = MVM_malloc(sizeof(MVMCallsite *) * 8);
        }
        interns->by_arity[num_flags][interns->num_by_arity[num_flags]++] = cs;
        cs->is_interned = 1;
    }

    /* Finally, release mutex. */
    uv_mutex_unlock(&tc->instance->mutex_callsite_interns);
}
Example #19
0
/* Destroys a decoding stream, freeing all associated memory (including the
 * buffers). */
void MVM_string_decodestream_destory(MVMThreadContext *tc, MVMDecodeStream *ds) {
    MVMDecodeStreamBytes *cur_bytes = ds->bytes_head;
    while (cur_bytes) {
        MVMDecodeStreamBytes *next_bytes = cur_bytes->next;
        MVM_free(cur_bytes->bytes);
        MVM_free(cur_bytes);
        cur_bytes = next_bytes;
    }
    MVM_unicode_normalizer_cleanup(tc, &(ds->norm));
    MVM_free(ds);
}
Example #20
0
void MVM_region_destroy(MVMThreadContext *tc, MVMRegionAlloc *alloc) {
    MVMRegionBlock *block = alloc->block;
    /* Free all of the allocated memory. */
    while (block) {
        MVMRegionBlock *prev = block->prev;
        MVM_free(block->buffer);
        MVM_free(block);
        block = prev;
    }
    alloc->block = NULL;
}
Example #21
0
void MVM_file_chmod(MVMThreadContext *tc, MVMString *f, MVMint64 flag) {
    char * const a = MVM_string_utf8_encode_C_string(tc, f);
    uv_fs_t req;

    if(uv_fs_chmod(tc->loop, &req, a, flag, NULL) < 0 ) {
        MVM_free(a);
        MVM_exception_throw_adhoc(tc, "Failed to set permissions on path: %s", uv_strerror(req.result));
    }

    MVM_free(a);
}
Example #22
0
/* Remove a directory recursively. */
void MVM_dir_rmdir(MVMThreadContext *tc, MVMString *path) {
    char * const pathname = MVM_string_utf8_encode_C_string(tc, path);
    uv_fs_t req;

    if(uv_fs_rmdir(tc->loop, &req, pathname, NULL) < 0 ) {
        MVM_free(pathname);
        MVM_exception_throw_adhoc(tc, "Failed to rmdir: %s", uv_strerror(req.result));
    }

    MVM_free(pathname);
}
Example #23
0
/* Clean up an arguments processing context. */
void MVM_args_proc_cleanup(MVMThreadContext *tc, MVMArgProcContext *ctx) {
    if (ctx->arg_flags) {
        MVM_free(ctx->arg_flags);
        MVM_free(ctx->args);
    }
    if (ctx->named_used_size > 64) {
        MVM_fixed_size_free(tc, tc->instance->fsa, ctx->named_used_size,
            ctx->named_used.byte_array);
        ctx->named_used_size = 0;
    }
}
Example #24
0
/* Opens a file, returning a synchronous file handle. */
MVMObject * MVM_file_open_fh(MVMThreadContext *tc, MVMString *filename, MVMString *mode) {
    char * const fname = MVM_string_utf8_c8_encode_C_string(tc, filename);
    int fd;
    int flag;
    STAT statbuf;

    /* Resolve mode description to flags. */
    char * const fmode  = MVM_string_utf8_encode_C_string(tc, mode);
    if (!resolve_open_mode(&flag, fmode)) {
        char *waste[] = { fname, fmode, NULL };
        MVM_exception_throw_adhoc_free(tc, waste,
            "Invalid open mode for file %s: %s", fname, fmode);
    }
    MVM_free(fmode);

    /* Try to open the file. */
#ifdef _WIN32
    flag |= _O_BINARY;
#endif
    if ((fd = open((const char *)fname, flag, DEFAULT_MODE)) == -1) {
        char *waste[] = { fname, NULL };
        const char *err = strerror(errno);
        MVM_exception_throw_adhoc_free(tc, waste, "Failed to open file %s: %s", fname, err);
    }

    /*  Check that we didn't open a directory by accident.
        If fstat fails, just move on: Most of the documented error cases should
        already have triggered when opening the file, and we can't do anything
        about the others; a failure also does not necessarily imply that the
        file descriptor cannot be used for reading/writing. */
    if (fstat(fd, &statbuf) == 0 && (statbuf.st_mode & S_IFMT) == S_IFDIR) {
        char *waste[] = { fname, NULL };
        if (close(fd) == -1) {
            const char *err = strerror(errno);
            MVM_exception_throw_adhoc_free(tc, waste,
                "Tried to open directory %s, which we failed to close: %s",
                fname, err);
        }
        MVM_exception_throw_adhoc_free(tc, waste, "Tried to open directory %s", fname);
    }

    /* Set up handle. */
    MVM_free(fname);
    {
        MVMIOFileData * const data   = MVM_calloc(1, sizeof(MVMIOFileData));
        MVMOSHandle   * const result = (MVMOSHandle *)MVM_repr_alloc_init(tc,
            tc->instance->boot_types.BOOTIO);
        data->fd          = fd;
        data->seekable    = MVM_platform_lseek(fd, 0, SEEK_CUR) != -1;
        result->body.ops  = &op_table;
        result->body.data = data;
        return (MVMObject *)result;
    }
}
Example #25
0
static void late_bound_find_method_return(MVMThreadContext *tc, void *sr_data) {
    FindMethodSRData *fm = (FindMethodSRData *)sr_data;
    if (MVM_is_null(tc, fm->res->o) || !IS_CONCRETE(fm->res->o)) {
        MVMObject *obj  = fm->obj;
        MVMString *name = fm->name;
        MVM_free(fm);
        die_over_missing_method(tc, obj, name);
    }
    else {
        MVM_free(fm);
    }
}
Example #26
0
/* rename one file to another. */
void MVM_file_rename(MVMThreadContext *tc, MVMString *src, MVMString *dest) {
    char * const a = MVM_string_utf8_encode_C_string(tc, src);
    char * const b = MVM_string_utf8_encode_C_string(tc, dest);
    uv_fs_t req;

    if(uv_fs_rename(tc->loop, &req, a, b, NULL) < 0 ) {
        MVM_free(a);
        MVM_free(b);
        MVM_exception_throw_adhoc(tc, "Failed to rename file: %s", uv_strerror(req.result));
    }

    MVM_free(a);
    MVM_free(b);
}
Example #27
0
static uv_stat_t file_info(MVMThreadContext *tc, MVMString *filename, MVMint32 use_lstat) {
    char * const a = MVM_string_utf8_encode_C_string(tc, filename);
    uv_fs_t req;

    if ((use_lstat
            ? uv_fs_lstat(tc->loop, &req, a, NULL)
            :  uv_fs_stat(tc->loop, &req, a, NULL)
        ) < 0) {
        MVM_free(a);
        MVM_exception_throw_adhoc(tc, "Failed to stat file: %s", uv_strerror(req.result));
    }

    MVM_free(a);
    return req.statbuf;
}
Example #28
0
void MVM_callsite_destroy(MVMCallsite *cs) {
    if (cs->flag_count) {
        MVM_free(cs->arg_flags);
    }

    if (cs->arg_names) {
        MVM_free(cs->arg_names);
    }

    if (cs->with_invocant) {
        MVM_callsite_destroy(cs->with_invocant);
    }

    MVM_free(cs);
}
Example #29
0
/* Frees data associated with the directory handle. */
static void gc_free(MVMThreadContext *tc, MVMObject *h, void *d) {
    MVMIODirIter *data = (MVMIODirIter *)d;
    if (data) {
#ifdef _WIN32
        if (data->dir_name)
            MVM_free(data->dir_name);
        if (data->dir_handle)
            FindClose(data->dir_handle);
#else
        if (data->dir_handle)
            closedir(data->dir_handle);
#endif
        MVM_free(data);
    }
}
Example #30
0
/* Actually, it may return sockaddr_in6 as well; it's not a problem for us, because we just
 * pass is straight to uv, and the first thing it does is it looks at the address family,
 * but it's a thing to remember if someone feels like peeking inside the returned struct. */
struct sockaddr * MVM_io_resolve_host_name(MVMThreadContext *tc, MVMString *host, MVMint64 port) {
    char *host_cstr = MVM_string_utf8_encode_C_string(tc, host);
    struct sockaddr *dest;
    struct addrinfo *result;
    int error;
    char port_cstr[8];
    snprintf(port_cstr, 8, "%d", (int)port);

    error = getaddrinfo(host_cstr, port_cstr, NULL, &result);
    MVM_free(host_cstr);
    if (error == 0) {
        if (result->ai_addr->sa_family == AF_INET6) {
            dest = MVM_malloc(sizeof(struct sockaddr_in6));
            memcpy(dest, result->ai_addr, sizeof(struct sockaddr_in6));
        } else {
            dest = MVM_malloc(sizeof(struct sockaddr));
            memcpy(dest, result->ai_addr, sizeof(struct sockaddr));
        }
    }
    else {
        MVM_exception_throw_adhoc(tc, "Failed to resolve host name");
    }
    freeaddrinfo(result);

    return dest;
}