Пример #1
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");
    }
}
Пример #2
0
/* Dump a spesh graph into string form, for debugging purposes. */
char * MVM_spesh_dump(MVMThreadContext *tc, MVMSpeshGraph *g) {
    MVMSpeshBB *cur_bb;

    /* Allocate buffer. */
    DumpStr ds;
    ds.alloc  = 8192;
    ds.buffer = MVM_malloc(ds.alloc);
    ds.pos    = 0;

    /* Dump name and CUID. */
    append(&ds, "Spesh of '");
    append_str(tc, &ds, g->sf->body.name);
    append(&ds, "' (cuid: ");
    append_str(tc, &ds, g->sf->body.cuuid);
    append(&ds, ", file: ");
    dump_fileinfo(tc, &ds, g);
    append(&ds, ")\n");
    if (g->cs)
        dump_callsite(tc, &ds, g);
    if (g->num_arg_guards)
        dump_arg_guards(tc, &ds, g);
    if (!g->cs && !g->num_arg_guards)
        append(&ds, "\n");

    /* Go over all the basic blocks and dump them. */
    cur_bb = g->entry;
    while (cur_bb) {
        dump_bb(tc, &ds, g, cur_bb);
        cur_bb = cur_bb->linear_next;
    }

    /* Dump facts. */
    append(&ds, "\nFacts:\n");
    dump_facts(tc, &ds, g);

    if (g->num_spesh_slots || g->num_log_slots) {
        append(&ds, "\nStats:\n");
        appendf(&ds, "    %d spesh slots\n", g->num_spesh_slots);
        appendf(&ds, "    %d log slots\n", g->num_log_slots);
    }

    if (g->num_log_slots) {
        dump_log_values(tc, &ds, g);
    }

    append(&ds, "\n");
    append_null(&ds);
    return ds.buffer;
}
Пример #3
0
/* Dumps a planned specialization into a string. */
char * MVM_spesh_dump_planned(MVMThreadContext *tc, MVMSpeshPlanned *p) {
    DumpStr ds;
    ds.alloc  = 8192;
    ds.buffer = MVM_malloc(ds.alloc);
    ds.pos    = 0;

    /* Dump kind of specialization and target. */
    switch (p->kind) {
        case MVM_SPESH_PLANNED_CERTAIN:
            append(&ds, "Certain");
            break;
        case MVM_SPESH_PLANNED_OBSERVED_TYPES:
            append(&ds, "Observed type");
            break;
        case MVM_SPESH_PLANNED_DERIVED_TYPES:
            append(&ds, "Derived type");
            break;
    }
    append(&ds, " specialization of '");
    append_str(tc, &ds, p->sf->body.name);
    append(&ds, "' (cuid: ");
    append_str(tc, &ds, p->sf->body.cuuid);
    append(&ds, ", file: ");
    dump_fileinfo(tc, &ds, p->sf);
    append(&ds, ")\n\n");

    /* Dump the callsite of the specialization. */
    if (p->cs_stats->cs) {
        append(&ds, "The specialization is for the callsite:\n");
        dump_callsite(tc, &ds, p->cs_stats->cs);
    }
    else {
        append(&ds, "The specialization is for when there is no interned callsite.\n");
    }

    /* Dump reasoning. */
    switch (p->kind) {
        case MVM_SPESH_PLANNED_CERTAIN:
            if (p->cs_stats->hits >= MVM_spesh_threshold(tc, p->sf))
                appendf(&ds,
                    "It was planned due to the callsite receiving %u hits.\n",
                    p->cs_stats->hits);
            else if (p->cs_stats->osr_hits >= MVM_SPESH_PLAN_CS_MIN_OSR)
                appendf(&ds,
                    "It was planned due to the callsite receiving %u OSR hits.\n",
                    p->cs_stats->osr_hits);
            else
                append(&ds, "It was planned for unknown reasons.\n");
            if (!p->sf->body.specializable)
                append(&ds, "The body contains no specializable instructions.\n");
            break;
        case MVM_SPESH_PLANNED_OBSERVED_TYPES: {
            MVMCallsite *cs = p->cs_stats->cs;
            MVMuint32 hit_percent = p->cs_stats->hits
               ? (100 * p->type_stats[0]->hits) / p->cs_stats->hits
               : 0;
            MVMuint32 osr_hit_percent = p->cs_stats->osr_hits
               ? (100 * p->type_stats[0]->osr_hits) / p->cs_stats->osr_hits
               : 0;
            append(&ds, "It was planned for the type tuple:\n");
            dump_stats_type_tuple(tc, &ds, cs, p->type_tuple, "    ");
            if (osr_hit_percent >= MVM_SPESH_PLAN_TT_OBS_PERCENT_OSR)
                appendf(&ds, "Which received %u OSR hits (%u%% of the %u callsite OSR hits).\n",
                    p->type_stats[0]->osr_hits, osr_hit_percent, p->cs_stats->osr_hits);
            else if (hit_percent >= MVM_SPESH_PLAN_TT_OBS_PERCENT)
                appendf(&ds, "Which received %u hits (%u%% of the %u callsite hits).\n",
                    p->type_stats[0]->hits, hit_percent, p->cs_stats->hits);
            else
                append(&ds, "For unknown reasons.\n");
            break;
        }
        case MVM_SPESH_PLANNED_DERIVED_TYPES:
            break;
    }

    appendf(&ds, "\nThe maximum stack depth is %d.\n\n", p->max_depth);
    append_null(&ds);
    return ds.buffer;
}
Пример #4
0
/* Dump a spesh graph into string form, for debugging purposes. */
char * MVM_spesh_dump(MVMThreadContext *tc, MVMSpeshGraph *g) {
    MVMSpeshBB *cur_bb;
    SpeshGraphSizeStats stats;
    InlineIndexStack inline_stack;
    DumpStr ds;

    stats.total_size = 0;
    stats.inlined_size = 0;
    inline_stack.cur_depth = -1;

    /* Allocate buffer. */
    ds.alloc  = 8192;
    ds.buffer = MVM_malloc(ds.alloc);
    ds.pos    = 0;

    /* Dump name and CUID. */
    append(&ds, "Spesh of '");
    append_str(tc, &ds, g->sf->body.name);
    append(&ds, "' (cuid: ");
    append_str(tc, &ds, g->sf->body.cuuid);
    append(&ds, ", file: ");
    dump_fileinfo(tc, &ds, g->sf);
    append(&ds, ")\n");
    if (g->cs)
        dump_callsite(tc, &ds, g->cs);
    if (!g->cs)
        append(&ds, "\n");

    /* Go over all the basic blocks and dump them. */
    cur_bb = g->entry;
    while (cur_bb) {
        dump_bb(tc, &ds, g, cur_bb, &stats, &inline_stack);
        cur_bb = cur_bb->linear_next;
    }

    /* Dump facts. */
    if (g->facts) {
        append(&ds, "\nFacts:\n");
        dump_facts(tc, &ds, g);
    }

    /* Dump spesh slots. */
    if (g->num_spesh_slots) {
        MVMuint32 i;
        append(&ds, "\nSpesh slots:\n");
        for (i = 0; i < g->num_spesh_slots; i++) {
            MVMCollectable *value = g->spesh_slots[i];
            if (value == NULL)
                appendf(&ds, "    %d = NULL\n", i);
            else if (value->flags & MVM_CF_STABLE)
                appendf(&ds, "    %d = STable (%s)\n", i,
                    MVM_6model_get_stable_debug_name(tc, (MVMSTable *)value));
            else if (value->flags & MVM_CF_TYPE_OBJECT)
                appendf(&ds, "    %d = Type Object (%s)\n", i,
                    MVM_6model_get_debug_name(tc, (MVMObject *)value));
            else {
                MVMObject *obj = (MVMObject *)value;
                MVMuint32 repr_id = REPR(obj)->ID;
                appendf(&ds, "    %d = Instance (%s)", i,
                    MVM_6model_get_debug_name(tc, obj));
                if (repr_id == MVM_REPR_ID_MVMStaticFrame || repr_id == MVM_REPR_ID_MVMCode) {
                    MVMStaticFrameBody *body;
                    char *name_str;
                    char *cuuid_str;
                    if (repr_id == MVM_REPR_ID_MVMCode) {
                        MVMCodeBody *code_body = (MVMCodeBody *)OBJECT_BODY(obj);
                        obj = (MVMObject *)code_body->sf;
                    }
                    body = (MVMStaticFrameBody *)OBJECT_BODY(obj);
                    name_str  = MVM_string_utf8_encode_C_string(tc, body->name);
                    cuuid_str = MVM_string_utf8_encode_C_string(tc, body->cuuid);
                    appendf(&ds, " - '%s' (%s)", name_str, cuuid_str);
                    MVM_free(name_str);
                    MVM_free(cuuid_str);
                }
                appendf(&ds, "\n");
            }
        }
    }

    /* Dump materialization deopt into. */
    dump_deopt_pea(tc, &ds, g);

    append(&ds, "\n");

    /* Print out frame size */
    if (stats.inlined_size)
        appendf(&ds, "Frame size: %u bytes (%u from inlined frames)\n", stats.total_size, stats.inlined_size);
    else
        appendf(&ds, "Frame size: %u bytes\n", stats.total_size);

    append_null(&ds);
    return ds.buffer;
}