コード例 #1
0
ファイル: dump.c プロジェクト: baby-gnu/MoarVM
/* Dumps the facts table. */
static void dump_facts(MVMThreadContext *tc, DumpStr *ds, MVMSpeshGraph *g) {
    MVMuint16 i, j, num_locals, num_facts;
    num_locals = g->num_locals;
    for (i = 0; i < num_locals; i++) {
        num_facts = g->fact_counts[i];
        for (j = 0; j < num_facts; j++) {
            MVMint32 usages = g->facts[i][j].usages;
            MVMint32 flags  = g->facts[i][j].flags;
            if (i < 10) append(ds, " ");
            if (j < 10) append(ds, " ");
            appendf(ds, "    r%d(%d): usages=%d, flags=%-5d", i, j, usages, flags);
            if (flags & 1) {
                append(ds, " KnTyp");
            }
            if (flags & 2) {
                append(ds, " KnVal");
            }
            if (flags & 4) {
                append(ds, " Dcntd");
            }
            if (flags & 8) {
                append(ds, " Concr");
            }
            if (flags & 16) {
                append(ds, " TyObj");
            }
            if (flags & 32) {
                append(ds, " KnDcT");
            }
            if (flags & 64) {
                append(ds, " DCncr");
            }
            if (flags & 128) {
                append(ds, " DcTyO");
            }
            if (flags & 256) {
                append(ds, " LogGd");
            }
            if (flags & 512) {
                append(ds, " HashI");
            }
            if (flags & 1024) {
                append(ds, " ArrIt");
            }
            if (flags & 2048) {
                append(ds, " KBxSr");
            }
            if (flags & 4096) {
                append(ds, " MgWLG");
            }
            if (flags & 8192) {
                append(ds, " KRWCn");
            }
            if (g->facts[i][j].writer && g->facts[i][j].writer->info->opcode == MVM_SSA_PHI) {
                appendf(ds, " (merged from %d regs)", g->facts[i][j].writer->info->num_operands - 1);
            }
            append(ds, "\n");
        }
    }
}
コード例 #2
0
ファイル: dump.c プロジェクト: MasterDuke17/MoarVM
static void dump_callsite(MVMThreadContext *tc, DumpStr *ds, MVMCallsite *cs) {
    MVMuint16 i;
    appendf(ds, "Callsite %p (%d args, %d pos)\n", cs, cs->arg_count, cs->num_pos);
    for (i = 0; i < (cs->arg_count - cs->num_pos) / 2; i++) {
        if (cs->arg_names[i]) {
            char * argname_utf8 = MVM_string_utf8_encode_C_string(tc, cs->arg_names[i]);
            appendf(ds, "  - %s\n", argname_utf8);
            MVM_free(argname_utf8);
        }
    }
    if (cs->num_pos)
        append(ds, "Positional flags: ");
    for (i = 0; i < cs->num_pos; i++) {
        MVMCallsiteEntry arg_flag = cs->arg_flags[i];

        if (i)
            append(ds, ", ");

        if (arg_flag == MVM_CALLSITE_ARG_OBJ) {
            append(ds, "obj");
        } else if (arg_flag == MVM_CALLSITE_ARG_INT) {
            append(ds, "int");
        } else if (arg_flag == MVM_CALLSITE_ARG_NUM) {
            append(ds, "num");
        } else if (arg_flag == MVM_CALLSITE_ARG_STR) {
            append(ds, "str");
        }
    }
    if (cs->num_pos)
        append(ds, "\n");
    append(ds, "\n");
}
コード例 #3
0
ファイル: dump.c プロジェクト: baby-gnu/MoarVM
/* 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;
}
コード例 #4
0
static gboolean osm_create_changeset(osm_upload_context_t *context, gchar **cred) {
  gboolean result = FALSE;
  context->changeset = ILLEGAL;
  project_t *project = context->project;

  /* make sure gui gets updated */
  while(gtk_events_pending()) gtk_main_iteration();

  char *url = g_strdup_printf("%s/changeset/create", project->server);
  appendf(&context->log, NULL, _("Create changeset "));

  /* create changeset request */
  char *xml_str = osm_generate_xml_changeset(context->comment);
  if(xml_str) {
    printf("creating changeset %s from address %p\n", url, xml_str);

    *cred = g_strjoin(":", context->appdata->settings->username,
                      context->appdata->settings->password, NULL);

    if(osm_update_item(&context->log, xml_str, url, *cred,
		       &context->changeset, context->proxy)) {
      printf("got changeset id " ITEM_ID_FORMAT "\n", context->changeset);
      result = TRUE;
    } else {
      g_free(*cred);
    }
  }
  g_free(url);

  return result;
}
コード例 #5
0
static void osm_delete_relations(osm_upload_context_t *context, gchar *cred) {
  relation_t *relation = context->osm->relation;
  project_t *project = context->project;

  for(; relation; relation = relation->next) {
    /* make sure gui gets updated */
    while(gtk_events_pending()) gtk_main_iteration();

    if(!(OSM_FLAGS(relation) & OSM_FLAG_DELETED))
      continue;

    printf("deleting relation on server\n");

    appendf(&context->log, NULL,
            _("Delete relation #" ITEM_ID_FORMAT " "), OSM_ID(relation));

    char *url = g_strdup_printf("%s/relation/" ITEM_ID_FORMAT,
                                project->server, OSM_ID(relation));
    char *xml_str = osm_generate_xml_relation(context->changeset, relation);

    if(osm_delete_item(&context->log, xml_str, url, cred, context->proxy)) {
      OSM_FLAGS(relation) &= ~(OSM_FLAG_DIRTY | OSM_FLAG_DELETED);
      project->data_dirty = TRUE;
    }
  }
}
コード例 #6
0
static void osm_delete_ways(osm_upload_context_t *context, gchar *cred) {
  way_t *way = context->osm->way;
  project_t *project = context->project;

  for(; way; way = way->next) {
    /* make sure gui gets updated */
    while(gtk_events_pending()) gtk_main_iteration();

    if(!(OSM_FLAGS(way) & OSM_FLAG_DELETED))
      continue;

    printf("deleting way on server\n");

    appendf(&context->log, NULL, _("Delete way #" ITEM_ID_FORMAT " "), OSM_ID(way));

    char *url = g_strdup_printf("%s/way/" ITEM_ID_FORMAT,
                                project->server, OSM_ID(way));
    char *xml_str = osm_generate_xml_way(context->changeset, way);

    if(osm_delete_item(&context->log, xml_str, url, cred, context->proxy)) {
      OSM_FLAGS(way) &= ~(OSM_FLAG_DIRTY | OSM_FLAG_DELETED);
      project->data_dirty = TRUE;
    }
  }
}
コード例 #7
0
static void osm_delete_nodes(osm_upload_context_t *context, gchar *cred) {
  node_t *node = context->osm->node;
  project_t *project = context->project;

  for(; node; node = node->next) {
    /* make sure gui gets updated */
    while(gtk_events_pending()) gtk_main_iteration();

    if(!(OSM_FLAGS(node) & OSM_FLAG_DELETED))
      continue;

    printf("deleting node on server\n");

    appendf(&context->log, NULL, _("Delete node #" ITEM_ID_FORMAT " "), OSM_ID(node));

    char *url = g_strdup_printf("%s/node/" ITEM_ID_FORMAT,
                                project->server, OSM_ID(node));

    char *xml_str = osm_generate_xml_node(context->changeset, node);

    if(osm_delete_item(&context->log, xml_str, url, cred, context->proxy)) {
      OSM_FLAGS(node) &= ~(OSM_FLAG_DIRTY | OSM_FLAG_DELETED);
      project->data_dirty = TRUE;
    }
  }
}
コード例 #8
0
ファイル: vmnet.cpp プロジェクト: cspiegel/garglk
    /* append text, converting plain text to URL encoding */
    void append_urlencode(const char *txt)
    {
        const char *p, *start;

        /* append in chunks as we find special characters */
        for (p = start = txt ; *p != '\0' ; ++p)
        {
            char c = *p;
            if (isalpha(c) || isdigit(c) || strchr("-_.", c) != 0)
            {
                /* it's an ordinary character - keep it as-is */
            }
            else
            {
                /* special character - quote it */

                /* copy the part up to the special character */
                if (p != start)
                    append(start, p - start);

                /* append '+' for a space or a '%' encoding for others */
                if (c == ' ')
                    append("+");
                else
                    appendf("%%%02x", (int)(unsigned char)c);

                /* the next chunk starts at the next character */
                start = p + 1;
            }
        }

        /* append the final chunk */
        if (p != start)
            append(start, p - start);
    }
コード例 #9
0
ファイル: dump.c プロジェクト: MasterDuke17/MoarVM
/* Dumps the statistics associated with a static frame into a string. */
char * MVM_spesh_dump_stats(MVMThreadContext *tc, MVMStaticFrame *sf) {
    MVMSpeshStats *ss = sf->body.spesh->body.spesh_stats;

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

    /* Dump name and CUID. */
    append(&ds, "Latest statistics for '");
    append_str(tc, &ds, sf->body.name);
    append(&ds, "' (cuid: ");
    append_str(tc, &ds, sf->body.cuuid);
    append(&ds, ", file: ");
    dump_fileinfo(tc, &ds, sf);
    append(&ds, ")\n\n");

    /* Dump the spesh stats if present. */
    if (ss) {
        MVMuint32 i;

        appendf(&ds, "Total hits: %d\n", ss->hits);
        if (ss->osr_hits)
            appendf(&ds, "OSR hits: %d\n", ss->osr_hits);
        append(&ds, "\n");

        for (i = 0; i < ss->num_by_callsite; i++)
            dump_stats_by_callsite(tc, &ds, &(ss->by_callsite[i]));

        if (ss->num_static_values) {
            append(&ds, "Static values:\n");
            for (i = 0; i < ss->num_static_values; i++)
                appendf(&ds, "    - %s (%p) @ %d\n",
                    MVM_6model_get_stable_debug_name(tc, ss->static_values[i].value->st),
                    ss->static_values[i].value,
                    ss->static_values[i].bytecode_offset);
        }
    }
    else {
        append(&ds, "No spesh stats for this static frame\n");
    }

    append(&ds, "\n");
    append_null(&ds);
    return ds.buffer;
}
コード例 #10
0
ファイル: dump.c プロジェクト: MasterDuke17/MoarVM
/* Dumps a spesh stats type typle. */
void dump_stats_type_tuple(MVMThreadContext *tc, DumpStr *ds, MVMCallsite *cs,
                           MVMSpeshStatsType *type_tuple, char *prefix) {
    MVMuint32 j;
    for (j = 0; j < cs->flag_count; j++) {
        MVMObject *type = type_tuple[j].type;
        if (type) {
            MVMObject *decont_type = type_tuple[j].decont_type;
            appendf(ds, "%sType %d: %s%s (%s)",
                prefix, j,
                (type_tuple[j].rw_cont ? "RW " : ""),
                MVM_6model_get_stable_debug_name(tc, type->st),
                (type_tuple[j].type_concrete ? "Conc" : "TypeObj"));
            if (decont_type)
                appendf(ds, " of %s (%s)",
                    MVM_6model_get_stable_debug_name(tc, decont_type->st),
                    (type_tuple[j].decont_type_concrete ? "Conc" : "TypeObj"));
            append(ds, "\n");
        }
    }
}
コード例 #11
0
ファイル: dump.c プロジェクト: baby-gnu/MoarVM
static void dump_arg_guards(MVMThreadContext *tc, DumpStr *ds, MVMSpeshGraph *g) {
    MVMuint16 i;
    appendf(ds, "%d argument guards\n", g->num_arg_guards);

    for (i = 0; i < g->num_arg_guards; i++) {
        MVMSpeshGuard *guard = &g->arg_guards[i];
        switch (guard->kind) {
        case MVM_SPESH_GUARD_CONC:
            appendf(ds, "  concrete(%d)\n", guard->slot);
            break;
        case MVM_SPESH_GUARD_TYPE:
            appendf(ds, "  type(%d, %p)", guard->slot, guard->match);
            if (((MVMSTable*)(guard->match))->debug_name) {
                appendf(ds, " debugname: %s", ((MVMSTable*)(guard->match))->debug_name);
            }
            append(ds, "\n");
            break;
        case MVM_SPESH_GUARD_DC_CONC:
            appendf(ds, "  deconted_concrete(%d)\n", guard->slot);
            break;
        case MVM_SPESH_GUARD_DC_TYPE:
            appendf(ds, "  deconted_type(%d, %p)", guard->slot, guard->match);
            if (((MVMSTable*)(guard->match))->debug_name) {
                appendf(ds, " debugname: %s", ((MVMSTable*)(guard->match))->debug_name);
            }
            append(ds, "\n");
            break;
        case MVM_SPESH_GUARD_DC_CONC_RW:
            appendf(ds, "  deconted_concrete_rw(%d)\n", guard->slot);
            break;
        case MVM_SPESH_GUARD_DC_TYPE_RW:
            appendf(ds, "  deconted_type_rw(%d, %p)", guard->slot, guard->match);
            if (((MVMSTable*)(guard->match))->debug_name) {
                appendf(ds, " debugname: %s", ((MVMSTable*)(guard->match))->debug_name);
            }
            append(ds, "\n");
            break;
        }
    }
    append(ds, "\n");
}
コード例 #12
0
ファイル: lua_bloom_filter.c プロジェクト: H5eye/lua_sandbox
int serialize_bloom_filter(const char* key, bloom_filter* bf, output_data* output)
{
  output->pos = 0;
  if (appendf(output,
              "if %s == nil then %s = bloom_filter.new(%d, %g) end\n",
              key,
              key,
              bf->items,
              bf->probability)) {
    return 1;
  }

  if (appendf(output, "%s:fromstring(\"", key)) {
    return 1;
  }
  if (serialize_binary(bf->data, bf->bytes, output)) return 1;
  if (appends(output, "\")\n")) {
    return 1;
  }
  return 0;
}
コード例 #13
0
ファイル: dump.c プロジェクト: MasterDuke17/MoarVM
static void dump_deopt_pea(MVMThreadContext *tc, DumpStr *ds, MVMSpeshGraph *g) {
    MVMint32 i, j;
    if (MVM_VECTOR_ELEMS(g->deopt_pea.materialize_info)) {
        append(ds, "\nMaterializations:\n");
        for (i = 0; i < MVM_VECTOR_ELEMS(g->deopt_pea.materialize_info); i++) {
            MVMSpeshPEAMaterializeInfo *mat = &(g->deopt_pea.materialize_info[i]);
            MVMSTable *st = (MVMSTable *)g->spesh_slots[mat->stable_sslot];
            appendf(ds, "  %d: %s from regs ", i, st->debug_name);
            for (j = 0; j < mat->num_attr_regs; j++)
                appendf(ds, j > 0 ? ", r%hu" : "r%hu", mat->attr_regs[j]);
            append(ds, "\n");
        }
    }
    if (MVM_VECTOR_ELEMS(g->deopt_pea.deopt_point)) {
        append(ds, "\nDeopt point materialization mappings:\n");
        for (i = 0; i < MVM_VECTOR_ELEMS(g->deopt_pea.deopt_point); i++) {
            MVMSpeshPEADeoptPoint *dp = &(g->deopt_pea.deopt_point[i]);
            appendf(ds, "  At %d materialize %d into r%d\n", dp->deopt_point_idx,
                    dp->materialize_info_idx, dp->target_reg);
        }
    }
}
コード例 #14
0
static void osm_upload_relations(osm_upload_context_t *context, gchar *cred) {
  relation_t *relation = context->osm->relation;
  project_t *project = context->project;

  for(; relation; relation = relation->next) {
    /* make sure gui gets updated */
    while(gtk_events_pending()) gtk_main_iteration();

    if(!(OSM_FLAGS(relation) & (OSM_FLAG_DIRTY | OSM_FLAG_NEW)) ||
       (OSM_FLAGS(relation) & OSM_FLAG_DELETED))
      continue;

    char *url = NULL;

    if(OSM_FLAGS(relation) & OSM_FLAG_NEW) {
      url = g_strdup_printf("%s/relation/create", project->server);
      appendf(&context->log, NULL, _("New relation "));
    } else {
      url = g_strdup_printf("%s/relation/" ITEM_ID_FORMAT,
                            project->server,OSM_ID(relation));
      appendf(&context->log, NULL, _("Modified relation #" ITEM_ID_FORMAT " "),
              OSM_ID(relation));
    }

    /* upload this relation */
    char *xml_str = osm_generate_xml_relation(context->changeset, relation);
    if(xml_str) {
      printf("uploading relation %s from address %p\n", url, xml_str);

      if(osm_update_item(&context->log, xml_str, url, cred,
         (OSM_FLAGS(relation) & OSM_FLAG_NEW) ? &(OSM_ID(relation)) :
          &OSM_VERSION(relation), context->proxy)) {
        OSM_FLAGS(relation) &= ~(OSM_FLAG_DIRTY | OSM_FLAG_NEW);
        project->data_dirty = TRUE;
      }
    }
    g_free(url);
  }
}
コード例 #15
0
static void osm_upload_ways(osm_upload_context_t *context, gchar *cred) {
  way_t *way = context->osm->way;
  project_t *project = context->project;

  for(; way; way = way->next) {
    /* make sure gui gets updated */
    while(gtk_events_pending()) gtk_main_iteration();

    if(!(OSM_FLAGS(way) & (OSM_FLAG_DIRTY | OSM_FLAG_NEW)) ||
       (OSM_FLAGS(way) & OSM_FLAG_DELETED))
      continue;

    char *url = NULL;

    if(OSM_FLAGS(way) & OSM_FLAG_NEW) {
      url = g_strconcat(project->server, "/way/create", NULL);
      appendf(&context->log, NULL, _("New way "));
    } else {
      url = g_strdup_printf("%s/way/" ITEM_ID_FORMAT,
                            project->server, OSM_ID(way));
      appendf(&context->log, NULL, _("Modified way #" ITEM_ID_FORMAT " "), OSM_ID(way));
    }

    /* upload this node */
    char *xml_str = osm_generate_xml_way(context->changeset, way);
    if(xml_str) {
      printf("uploading way %s from address %p\n", url, xml_str);

      if(osm_update_item(&context->log, xml_str, url, cred,
        (OSM_FLAGS(way) & OSM_FLAG_NEW) ? &(OSM_ID(way)) : &OSM_VERSION(way),
                         context->proxy)) {
        OSM_FLAGS(way) &= ~(OSM_FLAG_DIRTY | OSM_FLAG_NEW);
        project->data_dirty = TRUE;
      }
    }
    g_free(url);
  }
}
コード例 #16
0
ファイル: common.c プロジェクト: Ionic/mpv
// Return a talloc'ed string formatted according to the format string in fmt.
// On error, return NULL.
// Valid formats:
// %H, %h: hour (%H is padded with 0 to two digits)
// %M: minutes from 00-59 (hours are subtracted)
// %m: total minutes (includes hours, unlike %M)
// %S: seconds from 00-59 (minutes and hours are subtracted)
// %s: total seconds (includes hours and minutes)
// %f: like %s, but as float
// %T: milliseconds (000-999)
char *mp_format_time_fmt(const char *fmt, double time)
{
    if (time == MP_NOPTS_VALUE)
        return talloc_strdup(NULL, "unknown");
    char *sign = time < 0 ? "-" : "";
    time = time < 0 ? -time : time;
    long long int itime = time;
    long long int h, m, tm, s;
    int ms;
    s = itime;
    tm = s / 60;
    h = s / 3600;
    s -= h * 3600;
    m = s / 60;
    s -= m * 60;
    ms = (time - itime) * 1000;
    char *res = talloc_strdup(NULL, "");
    while (*fmt) {
        if (fmt[0] == '%') {
            fmt++;
            switch (fmt[0]) {
            case 'h': appendf(&res, "%s%lld", sign, h); break;
            case 'H': appendf(&res, "%s%02lld", sign, h); break;
            case 'm': appendf(&res, "%s%lld", sign, tm); break;
            case 'M': appendf(&res, "%02lld", m); break;
            case 's': appendf(&res, "%s%lld", sign, itime); break;
            case 'S': appendf(&res, "%02lld", s); break;
            case 'T': appendf(&res, "%03d", ms); break;
            case '%': appendf(&res, "%s", "%"); break;
            default: goto error;
            }
            fmt++;
        } else {
            appendf(&res, "%c", *fmt);
            fmt++;
        }
    }
    return res;
error:
    talloc_free(res);
    return NULL;
}
コード例 #17
0
ファイル: dump.c プロジェクト: MasterDuke17/MoarVM
/* Dump deopt usages. */
static void dump_deopt_usages(MVMThreadContext *tc, DumpStr *ds, MVMSpeshGraph *g, MVMSpeshOperand operand) {
    MVMSpeshFacts *facts = MVM_spesh_get_facts(tc, g, operand);
    MVMSpeshDeoptUseEntry *entry = facts->usage.deopt_users;
    if (entry) {
        MVMuint32 first = 1;
        append(ds, ", deopt=");
        while (entry) {
            if (first)
                first = 0;
            else
                append(ds, ",");
            appendf(ds, "%d", entry->deopt_idx);
            entry = entry->next;
        }
    }
}
コード例 #18
0
ファイル: dump.c プロジェクト: MasterDuke17/MoarVM
static void dump_fileinfo(MVMThreadContext *tc, DumpStr *ds, MVMStaticFrame *sf) {
    MVMBytecodeAnnotation *ann = MVM_bytecode_resolve_annotation(tc, &sf->body, 0);
    MVMCompUnit            *cu = sf->body.cu;
    MVMint32           str_idx = ann ? ann->filename_string_heap_index : 0;
    MVMint32           line_nr = ann ? ann->line_number : 1;
    MVMString        *filename = cu->body.filename;
    char        *filename_utf8 = "<unknown>";
    if (ann && str_idx < cu->body.num_strings) {
        filename = MVM_cu_string(tc, cu, str_idx);
    }
    if (filename)
        filename_utf8 = MVM_string_utf8_encode_C_string(tc, filename);
    appendf(ds, "%s:%d", filename_utf8, line_nr);
    if (filename)
        MVM_free(filename_utf8);
    MVM_free(ann);
}
コード例 #19
0
static gboolean osm_close_changeset(osm_upload_context_t *context, gchar *cred) {
  gboolean result = FALSE;
  project_t *project = context->project;

  g_assert(context->changeset != ILLEGAL);

  /* make sure gui gets updated */
  while(gtk_events_pending()) gtk_main_iteration();

  char *url = g_strdup_printf("%s/changeset/" ITEM_ID_FORMAT "/close",
			      project->server, context->changeset);
  appendf(&context->log, NULL, _("Close changeset "));

  if(osm_update_item(&context->log, NULL, url, cred, NULL, context->proxy))
    result = TRUE;

  g_free(cred);
  g_free(url);

  return result;
}
コード例 #20
0
int serialize_data_as_json(lua_sandbox* lsb, int index, output_data* output)
{
  const char* s;
  size_t len = 0;
  size_t start_pos = output->pos;
  size_t escaped_len = 0;
  switch (lua_type(lsb->lua, index)) {
  case LUA_TNUMBER:
    if (serialize_double(output, lua_tonumber(lsb->lua, index))) {
      return 1;
    }
    break;
  case LUA_TSTRING:
    s = lua_tolstring(lsb->lua, index, &len);
    escaped_len = len + 3; // account for the quotes and terminator
    if (output->pos + escaped_len > output->size) {
      if (realloc_output(output, escaped_len)) return 1;
    }
    output->data[output->pos++] = '"';

    for (size_t i = 0; i < len; ++i) {
      // buffer needs at least enough room for an escaped character, an end
      // quote and a null terminator
      if (output->pos + 4 > output->size) {
        size_t needed = escaped_len - (output->pos - start_pos);
        if (realloc_output(output, needed)) return 1;
      }
      switch (s[i]) {
      case '"':
        output->data[output->pos++] = '\\';
        output->data[output->pos++] = '"';
        ++escaped_len;
        break;
      case '\\':
        output->data[output->pos++] = '\\';
        output->data[output->pos++] = '\\';
        ++escaped_len;
        break;
      case '/':
        output->data[output->pos++] = '\\';
        output->data[output->pos++] = '/';
        ++escaped_len;
        break;
      case '\b':
        output->data[output->pos++] = '\\';
        output->data[output->pos++] = 'b';
        ++escaped_len;
        break;
      case '\f':
        output->data[output->pos++] = '\\';
        output->data[output->pos++] = 'f';
        ++escaped_len;
        break;
      case '\n':
        output->data[output->pos++] = '\\';
        output->data[output->pos++] = 'n';
        ++escaped_len;
        break;
      case '\r':
        output->data[output->pos++] = '\\';
        output->data[output->pos++] = 'r';
        ++escaped_len;
        break;
      case '\t':
        output->data[output->pos++] = '\\';
        output->data[output->pos++] = 't';
        ++escaped_len;
        break;
      default:
        output->data[output->pos++] = s[i];
      }
    }
    output->data[output->pos++] = '"';
    output->data[output->pos] = 0;
    break;
  case LUA_TBOOLEAN:
    if (appendf(output, "%s", lua_toboolean(lsb->lua, index)
                ? "true" : "false")) {
      return 1;
    }
  case LUA_TNIL:
    break;
  default:
    snprintf(lsb->error_message, LSB_ERROR_SIZE,
             "serialize_data_as_json cannot preserve type '%s'",
             lua_typename(lsb->lua, lua_type(lsb->lua, index)));
    return 1;
  }
  return 0;
}
コード例 #21
0
ファイル: dump.c プロジェクト: mj41/MoarVM
/* Dumps a basic block. */
static void dump_bb(MVMThreadContext *tc, DumpStr *ds, MVMSpeshGraph *g, MVMSpeshBB *bb) {
    MVMSpeshIns *cur_ins;
    MVMint64     i;

    /* Heading. */
    appendf(ds, "  BB %d:\n", bb->idx);

    /* Instructions. */
    append(ds, "    Instructions:\n");
    cur_ins = bb->first_ins;
    while (cur_ins) {
        MVMSpeshAnn *ann = cur_ins->annotations;
        while (ann) {
            switch (ann->type) {
                case MVM_SPESH_ANN_FH_START:
                    appendf(ds, "      [Annotation: FH Start (%d)]\n",
                        ann->data.frame_handler_index);
                    break;
                case MVM_SPESH_ANN_FH_END:
                    appendf(ds, "      [Annotation: FH End (%d)]\n",
                        ann->data.frame_handler_index);
                    break;
                case MVM_SPESH_ANN_FH_GOTO:
                    appendf(ds, "      [Annotation: FH Goto (%d)]\n",
                        ann->data.frame_handler_index);
                    break;
                default:
                    appendf(ds, "      [Annotation: %d (unknown)]\n", ann->type);
            }
            ann = ann->next;
        }

        appendf(ds, "      %s ", cur_ins->info->name);
        if (cur_ins->info->opcode == MVM_SSA_PHI) {
            for (i = 0; i < cur_ins->info->num_operands; i++) {
                if (i)
                    append(ds, ", ");
                appendf(ds, "r%d(%d)", cur_ins->operands[i].reg.orig,
                    cur_ins->operands[i].reg.i);
            }
        }
        else {
            for (i = 0; i < cur_ins->info->num_operands; i++) {
                if (i)
                    append(ds, ", ");
                switch (cur_ins->info->operands[i] & MVM_operand_rw_mask) {
                    case MVM_operand_read_reg:
                    case MVM_operand_write_reg:
                        appendf(ds, "r%d(%d)", cur_ins->operands[i].reg.orig,
                            cur_ins->operands[i].reg.i);
                        break;
                    case MVM_operand_literal: {
                        MVMuint32 type = cur_ins->info->operands[i] & MVM_operand_type_mask;
                        switch (type) {
                        case MVM_operand_ins:
                            appendf(ds, "BB(%d)", cur_ins->operands[i].ins_bb->idx);
                            break;
                        case MVM_operand_int8:
                            appendf(ds, "liti8(%d)", cur_ins->operands[i].lit_i8);
                            break;
                        case MVM_operand_int16:
                            appendf(ds, "liti16(%d)", cur_ins->operands[i].lit_i16);
                            break;
                        case MVM_operand_int32:
                            appendf(ds, "liti32(%d)", cur_ins->operands[i].lit_i32);
                            break;
                        case MVM_operand_int64:
                            appendf(ds, "liti64(%d)", cur_ins->operands[i].lit_i64);
                            break;
                        case MVM_operand_num32:
                            appendf(ds, "litn32(%d)", cur_ins->operands[i].lit_n32);
                            break;
                        case MVM_operand_num64:
                            appendf(ds, "litn64(%d)", cur_ins->operands[i].lit_n64);
                            break;
                        default:
                            append(ds, "<nyi(lit)>");
                        }
                        break;
                    }
                    default:
                        append(ds, "<nyi>");
                }
            }
        }
        append(ds, "\n");
        cur_ins = cur_ins->next;
    }

    /* Predecessors and successors. */
    append(ds, "    Successors: ");
    for (i = 0; i < bb->num_succ; i++)
        appendf(ds, (i == 0 ? "%d" : ", %d"), bb->succ[i]->idx);
    append(ds, "\n    Predeccessors: ");
    for (i = 0; i < bb->num_pred; i++)
        appendf(ds, (i == 0 ? "%d" : ", %d"), bb->pred[i]->idx);
    append(ds, "\n    Dominance children: ");
    for (i = 0; i < bb->num_children; i++)
        appendf(ds, (i == 0 ? "%d" : ", %d"), bb->children[i]->idx);
    append(ds, "\n\n");
}
コード例 #22
0
ファイル: dump.c プロジェクト: MasterDuke17/MoarVM
/* Dumps a static frame's guard set into a string. */
char * MVM_spesh_dump_arg_guard(MVMThreadContext *tc, MVMStaticFrame *sf) {
    MVMSpeshArgGuard *ag = sf->body.spesh->body.spesh_arg_guard;

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

    /* Dump name and CUID. */
    append(&ds, "Latest guard tree for '");
    append_str(tc, &ds, sf->body.name);
    append(&ds, "' (cuid: ");
    append_str(tc, &ds, sf->body.cuuid);
    append(&ds, ", file: ");
    dump_fileinfo(tc, &ds, sf);
    append(&ds, ")\n\n");

    /* Dump nodes. */
    if (ag) {
        MVMuint32 i = 0;
        for (i = 0; i < ag->used_nodes; i++) {
            MVMSpeshArgGuardNode *agn = &(ag->nodes[i]);
            switch (agn->op) {
                case MVM_SPESH_GUARD_OP_CALLSITE:
                    appendf(&ds, "%u: CALLSITE %p | Y: %u, N: %u\n",
                        i, agn->cs, agn->yes, agn->no);
                    break;
                case MVM_SPESH_GUARD_OP_LOAD_ARG:
                    appendf(&ds, "%u: LOAD ARG %d | Y: %u\n",
                        i, agn->arg_index, agn->yes);
                    break;
                case MVM_SPESH_GUARD_OP_STABLE_CONC:
                    appendf(&ds, "%u: STABLE CONC %s | Y: %u, N: %u\n",
                        i, MVM_6model_get_stable_debug_name(tc, agn->st), agn->yes, agn->no);
                    break;
                case MVM_SPESH_GUARD_OP_STABLE_TYPE:
                    appendf(&ds, "%u: STABLE CONC %s | Y: %u, N: %u\n",
                        i, MVM_6model_get_stable_debug_name(tc, agn->st), agn->yes, agn->no);
                    break;
                case MVM_SPESH_GUARD_OP_DEREF_VALUE:
                    appendf(&ds, "%u: DEREF_VALUE %u | Y: %u, N: %u\n",
                        i, agn->offset, agn->yes, agn->no);
                    break;
                case MVM_SPESH_GUARD_OP_DEREF_RW:
                    appendf(&ds, "%u: DEREF_RW %u | Y: %u, N: %u\n",
                        i, agn->offset, agn->yes, agn->no);
                    break;
                case MVM_SPESH_GUARD_OP_CERTAIN_RESULT:
                    appendf(&ds, "%u: CERTAIN RESULT %u\n", i, agn->result);
                    break;
                case MVM_SPESH_GUARD_OP_RESULT:
                    appendf(&ds, "%u: RESULT %u\n", i, agn->result);
                    break;
            }
        }
    }
    else {
        append(&ds, "No argument guard nodes\n");
    }

    append(&ds, "\n");
    append_null(&ds);
    return ds.buffer;
}
コード例 #23
0
ファイル: dump.c プロジェクト: MasterDuke17/MoarVM
/* Dumps a basic block. */
static void dump_bb(MVMThreadContext *tc, DumpStr *ds, MVMSpeshGraph *g, MVMSpeshBB *bb,
                    SpeshGraphSizeStats *stats, InlineIndexStack *inline_stack) {
    MVMSpeshIns *cur_ins;
    MVMint64     i;
    MVMint32     size = 0;

    /* Heading. */
    appendf(ds, "  BB %d (%p):\n", bb->idx, bb);

    if (bb->inlined) {
        append(ds, "    Inlined\n");
    }

    {
        /* Also, we have a line number */
        MVMBytecodeAnnotation *bbba = MVM_bytecode_resolve_annotation(tc, &g->sf->body, bb->initial_pc);
        MVMuint32 line_number;
        if (bbba) {
            line_number = bbba->line_number;
            MVM_free(bbba);
        } else {
            line_number = -1;
        }
        appendf(ds, "    line: %d (pc %d)\n", line_number, bb->initial_pc);
    }

    /* Instructions. */
    append(ds, "    Instructions:\n");
    cur_ins = bb->first_ins;
    while (cur_ins) {
        MVMSpeshAnn *ann = cur_ins->annotations;
        MVMuint32 line_number;
        MVMuint32 pop_inlines = 0;
        MVMuint32 num_comments = 0;

        while (ann) {
            /* These four annotations carry a deopt index that we can find a
             * corresponding line number for */
            if (ann->type == MVM_SPESH_ANN_DEOPT_ONE_INS
                || ann->type == MVM_SPESH_ANN_DEOPT_ALL_INS
                || ann->type == MVM_SPESH_ANN_DEOPT_INLINE
                || ann->type == MVM_SPESH_ANN_DEOPT_OSR) {
                MVMBytecodeAnnotation *ba = MVM_bytecode_resolve_annotation(tc, &g->sf->body, g->deopt_addrs[2 * ann->data.deopt_idx]);
                if (ba) {
                    line_number = ba->line_number;
                    MVM_free(ba);
                } else {
                    line_number = -1;
                }
            }
            switch (ann->type) {
                case MVM_SPESH_ANN_FH_START:
                    appendf(ds, "      [Annotation: FH Start (%d)]\n",
                        ann->data.frame_handler_index);
                    break;
                case MVM_SPESH_ANN_FH_END:
                    appendf(ds, "      [Annotation: FH End (%d)]\n",
                        ann->data.frame_handler_index);
                    break;
                case MVM_SPESH_ANN_FH_GOTO:
                    appendf(ds, "      [Annotation: FH Goto (%d)]\n",
                        ann->data.frame_handler_index);
                    break;
                case MVM_SPESH_ANN_DEOPT_ONE_INS:
                    appendf(ds, "      [Annotation: INS Deopt One (idx %d -> pc %d; line %d)]\n",
                        ann->data.deopt_idx, g->deopt_addrs[2 * ann->data.deopt_idx], line_number);
                    break;
                case MVM_SPESH_ANN_DEOPT_ALL_INS:
                    appendf(ds, "      [Annotation: INS Deopt All (idx %d -> pc %d; line %d)]\n",
                        ann->data.deopt_idx, g->deopt_addrs[2 * ann->data.deopt_idx], line_number);
                    break;
                case MVM_SPESH_ANN_INLINE_START:
                    appendf(ds, "      [Annotation: Inline Start (%d)]\n",
                        ann->data.inline_idx);
                    push_inline(tc, inline_stack, ann->data.inline_idx);
                    break;
                case MVM_SPESH_ANN_INLINE_END:
                    appendf(ds, "      [Annotation: Inline End (%d)]\n",
                        ann->data.inline_idx);
                    pop_inlines++;
                    break;
                case MVM_SPESH_ANN_DEOPT_INLINE:
                    appendf(ds, "      [Annotation: INS Deopt Inline (idx %d -> pc %d; line %d)]\n",
                        ann->data.deopt_idx, g->deopt_addrs[2 * ann->data.deopt_idx], line_number);
                    break;
                case MVM_SPESH_ANN_DEOPT_OSR:
                    appendf(ds, "      [Annotation: INS Deopt OSR (idx %d -> pc %d); line %d]\n",
                        ann->data.deopt_idx, g->deopt_addrs[2 * ann->data.deopt_idx], line_number);
                    break;
                case MVM_SPESH_ANN_LINENO: {
                    char *cstr;
                    MVMCompUnit *cu = get_current_cu(tc, g, inline_stack);
                    if (cu->body.num_strings < ann->data.lineno.filename_string_index) {
                        appendf(ds, "      [Annotation: Line Number: <out of bounds>:%d]\n",
                        ann->data.lineno.line_number);
                    }
                    else {
                        cstr = MVM_string_utf8_encode_C_string(tc,
                            MVM_cu_string(tc, get_current_cu(tc, g, inline_stack),
                            ann->data.lineno.filename_string_index));
                        appendf(ds, "      [Annotation: Line Number: %s:%d]\n",
                            cstr, ann->data.lineno.line_number);
                        MVM_free(cstr);
                    }
                    break;
                }
                case MVM_SPESH_ANN_LOGGED:
                    appendf(ds, "      [Annotation: Logged (bytecode offset %d)]\n",
                        ann->data.bytecode_offset);
                    break;
                case MVM_SPESH_ANN_DEOPT_SYNTH:
                    appendf(ds, "      [Annotation: INS Deopt Synth (idx %d)]\n",
                        ann->data.deopt_idx);
                    break;
                case MVM_SPESH_ANN_COMMENT:
                    num_comments++;
                    break;
                default:
                    appendf(ds, "      [Annotation: %d (unknown)]\n", ann->type);
            }
            ann = ann->next;
        }
        while (pop_inlines--)
            pop_inline(tc, inline_stack);

        if (num_comments > 1) {
            ann = cur_ins->annotations;
            while (ann) {
                if (ann->type == MVM_SPESH_ANN_COMMENT) {
                    appendf(ds, "      # %s\n", ann->data.comment);
                }
                ann = ann->next;
            }
        }

        appendf(ds, "      %-15s ", cur_ins->info->name);
        if (cur_ins->info->opcode == MVM_SSA_PHI) {
            for (i = 0; i < cur_ins->info->num_operands; i++) {
                MVMint16 orig = cur_ins->operands[i].reg.orig;
                MVMint16 regi = cur_ins->operands[i].reg.i;
                if (i)
                    append(ds, ", ");
                if (orig < 10) append(ds, " ");
                if (regi < 10) append(ds, " ");
                appendf(ds, "r%d(%d)", orig, regi);
            }
        }
        else {
            /* Count the opcode itself */
            size += 2;
            for (i = 0; i < cur_ins->info->num_operands; i++) {
                if (i)
                    append(ds, ", ");
                switch (cur_ins->info->operands[i] & MVM_operand_rw_mask) {
                    case MVM_operand_read_reg:
                    case MVM_operand_write_reg: {
                        MVMint16 orig = cur_ins->operands[i].reg.orig;
                        MVMint16 regi = cur_ins->operands[i].reg.i;
                        if (orig < 10) append(ds, " ");
                        if (regi < 10) append(ds, " ");
                        appendf(ds, "r%d(%d)", orig, regi);
                        size += 4;
                        break;
                    }
                    case MVM_operand_read_lex:
                    case MVM_operand_write_lex: {
                        MVMStaticFrameBody *cursor = &g->sf->body;
                        MVMuint32 ascension;
                        appendf(ds, "lex(idx=%d,outers=%d", cur_ins->operands[i].lex.idx,
                            cur_ins->operands[i].lex.outers);
                        for (ascension = 0;
                                ascension < cur_ins->operands[i].lex.outers;
                                ascension++, cursor = &cursor->outer->body) { };
                        if (cursor->fully_deserialized) {
                            if (cur_ins->operands[i].lex.idx < cursor->num_lexicals) {
                                char *cstr = MVM_string_utf8_encode_C_string(tc, cursor->lexical_names_list[cur_ins->operands[i].lex.idx]->key);
                                appendf(ds, ",%s)", cstr);
                                MVM_free(cstr);
                            } else {
                                append(ds, ",<out of bounds>)");
                            }
                        } else {
                            append(ds, ",<pending deserialization>)");
                        }
                        size += 4;
                        break;
                    }
                    case MVM_operand_literal: {
                        MVMuint32 type = cur_ins->info->operands[i] & MVM_operand_type_mask;
                        switch (type) {
                        case MVM_operand_ins: {
                            MVMint32 bb_idx = cur_ins->operands[i].ins_bb->idx;
                            if (bb_idx < 100) append(ds, " ");
                            if (bb_idx < 10)  append(ds, " ");
                            appendf(ds, "BB(%d)", bb_idx);
                            size += 4;
                            break;
                        }
                        case MVM_operand_int8:
                            appendf(ds, "liti8(%"PRId8")", cur_ins->operands[i].lit_i8);
                            size += 2;
                            break;
                        case MVM_operand_int16:
                            appendf(ds, "liti16(%"PRId16")", cur_ins->operands[i].lit_i16);
                            size += 2;
                            break;
                        case MVM_operand_int32:
                            appendf(ds, "liti32(%"PRId32")", cur_ins->operands[i].lit_i32);
                            size += 4;
                            break;
                        case MVM_operand_uint32:
                            appendf(ds, "litui32(%"PRIu32")", cur_ins->operands[i].lit_ui32);
                            size += 4;
                            break;
                        case MVM_operand_int64:
                            appendf(ds, "liti64(%"PRId64")", cur_ins->operands[i].lit_i64);
                            size += 8;
                            break;
                        case MVM_operand_num32:
                            appendf(ds, "litn32(%f)", cur_ins->operands[i].lit_n32);
                            size += 4;
                            break;
                        case MVM_operand_num64:
                            appendf(ds, "litn64(%g)", cur_ins->operands[i].lit_n64);
                            size += 8;
                            break;
                        case MVM_operand_str: {
                            char *cstr = MVM_string_utf8_encode_C_string(tc,
                                MVM_cu_string(tc, g->sf->body.cu, cur_ins->operands[i].lit_str_idx));
                            appendf(ds, "lits(%s)", cstr);
                            MVM_free(cstr);
                            size += 8;
                            break;
                        }
                        case MVM_operand_callsite: {
                            MVMCallsite *callsite = g->sf->body.cu->body.callsites[cur_ins->operands[i].callsite_idx];
                            appendf(ds, "callsite(%p, %d arg, %d pos, %s, %s)",
                                    callsite,
                                    callsite->arg_count, callsite->num_pos,
                                    callsite->has_flattening ? "flattening" : "nonflattening",
                                    callsite->is_interned ? "interned" : "noninterned");
                            size += 2;
                            break;

                        }
                        case MVM_operand_spesh_slot:
                            appendf(ds, "sslot(%"PRId16")", cur_ins->operands[i].lit_i16);
                            size += 2;
                            break;
                        case MVM_operand_coderef: {
                            MVMCodeBody *body = &((MVMCode*)g->sf->body.cu->body.coderefs[cur_ins->operands[i].coderef_idx])->body;
                            MVMBytecodeAnnotation *anno = MVM_bytecode_resolve_annotation(tc, &body->sf->body, 0);

                            append(ds, "coderef(");

                            if (anno) {
                                char *filestr = MVM_string_utf8_encode_C_string(tc,
                                    MVM_cu_string(tc, g->sf->body.cu, anno->filename_string_heap_index));
                                appendf(ds, "%s:%d%s)", filestr, anno->line_number, body->outer ? " (closure)" : "");
                                MVM_free(filestr);
                            } else {
                                append(ds, "??\?)");
                            }

                            size += 2;

                            MVM_free(anno);
                            break;
                        }
                        default:
                            append(ds, "<nyi(lit)>");
                        }
                        break;
                    }
                    default:
                        append(ds, "<nyi>");
                }
            }
            if (cur_ins->info->opcode == MVM_OP_wval || cur_ins->info->opcode == MVM_OP_wval_wide) {
                /* We can try to find out what the debug_name of this thing is. */
                MVMint16 dep = cur_ins->operands[1].lit_i16;
                MVMint64 idx;
                MVMCollectable *result = NULL;
                MVMSerializationContext *sc;
                char *debug_name = NULL;
                const char *repr_name = NULL;
                if (cur_ins->info->opcode == MVM_OP_wval) {
                    idx = cur_ins->operands[2].lit_i16;
                } else {
                    idx = cur_ins->operands[2].lit_i64;
                }
                sc = MVM_sc_get_sc(tc, g->sf->body.cu, dep);
                if (sc)
                    result = (MVMCollectable *)MVM_sc_try_get_object(tc, sc, idx);
                if (result) {
                    if (result->flags & MVM_CF_STABLE) {
                        debug_name = MVM_6model_get_stable_debug_name(tc, (MVMSTable *)result);
                        repr_name  = ((MVMSTable *)result)->REPR->name;
                    } else {
                        debug_name = MVM_6model_get_debug_name(tc, (MVMObject *)result);
                        repr_name  = REPR(result)->name;
                    }
                    if (debug_name) {
                        appendf(ds, " (%s: %s)", repr_name, debug_name);
                    } else {
                        appendf(ds, " (%s: ?)", repr_name);
                    }
                } else {
                    appendf(ds, " (not deserialized)");
                }
            }
        }
        if (num_comments == 1) {
            ann = cur_ins->annotations;
            while (ann) {
                if (ann->type == MVM_SPESH_ANN_COMMENT) {
                    appendf(ds, "  # %s", ann->data.comment);
                    break;
                }
                ann = ann->next;
            }
        }
        append(ds, "\n");
        cur_ins = cur_ins->next;
    }

    if (stats) {
        if (bb->inlined)
            stats->inlined_size += size;
        stats->total_size += size;
    }

    /* Predecessors and successors. */
    append(ds, "    Successors: ");
    for (i = 0; i < bb->num_succ; i++)
        appendf(ds, (i == 0 ? "%d" : ", %d"), bb->succ[i]->idx);
    append(ds, "\n    Predecessors: ");
    for (i = 0; i < bb->num_pred; i++)
        appendf(ds, (i == 0 ? "%d" : ", %d"), bb->pred[i]->idx);
    append(ds, "\n    Dominance children: ");
    for (i = 0; i < bb->num_children; i++)
        appendf(ds, (i == 0 ? "%d" : ", %d"), bb->children[i]->idx);
    append(ds, "\n\n");
}
コード例 #24
0
ファイル: dump.c プロジェクト: MasterDuke17/MoarVM
/* 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;
}
コード例 #25
0
static gboolean osm_delete_item(struct log_s *log, char *xml_str,
				char *url, char *user, proxy_t *proxy) {
  int retry = MAX_TRY;
  char buffer[CURL_ERROR_SIZE];

  CURL *curl;
  CURLcode res;

  /* delete has a payload since api 0.6 */
  curl_data_t read_data;
  curl_data_t write_data;

  while(retry >= 0) {

    if(retry != MAX_TRY)
      appendf(log, NULL, _("Retry %d/%d "), MAX_TRY-retry, MAX_TRY-1);

    /* get a curl handle */
    curl = curl_easy_init();
    if(!curl) {
      appendf(log, NULL, _("CURL init error\n"));
      return FALSE;
    }

    read_data.ptr = xml_str;
    read_data.len = xml_str?strlen(xml_str):0;
    write_data.ptr = NULL;
    write_data.len = 0;

    /* we want to use our own read/write functions */
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);

    curl_easy_setopt(curl, CURLOPT_INFILESIZE, (curl_off_t)read_data.len);

    /* now specify which file to upload */
    curl_easy_setopt(curl, CURLOPT_READDATA, &read_data);

    /* we pass our 'chunk' struct to the callback function */
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_data);

    /* enable uploading */
    curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);

    /* no read/write functions required */
    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");

    /* specify target URL, and note that this URL should include a file
       name, not only a directory */
    curl_easy_setopt(curl, CURLOPT_URL, url);

	curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);

    /* some servers don't like requests that are made without a user-agent
       field, so we provide one */
    curl_easy_setopt(curl, CURLOPT_USERAGENT, PACKAGE "-libcurl/" VERSION);

#ifdef NO_EXPECT
    struct curl_slist *slist = NULL;
    slist = curl_slist_append(slist, "Expect:");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
#endif

    curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, buffer);

    /* set user name and password for the authentication */
    curl_easy_setopt(curl, CURLOPT_USERPWD, user);

    net_io_set_proxy(curl, proxy);

    /* Now run off and do what you've been told! */
    res = curl_easy_perform(curl);

    long response;
    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);

    /* always cleanup */
#ifdef NO_EXPECT
    curl_slist_free_all(slist);
#endif
    curl_easy_cleanup(curl);

    if(res != 0)
      appendf(log, COLOR_ERR, _("failed: %s\n"), buffer);
    else if(response != 200)
      appendf(log, COLOR_ERR, _("failed, code: %ld %s\n"),
	      response, osm_http_message(response));
    else
      appendf(log, COLOR_OK, _("ok\n"));

    /* if it's neither "ok" (200), nor "internal server error" (500) */
    /* then write the message to the log */
    if((response != 200) && (response != 500) && write_data.ptr) {
      appendf(log, NULL, _("Server reply: "));
      appendf(log, COLOR_ERR, _("%s\n"), write_data.ptr);
    }

    g_free(write_data.ptr);

    /* don't retry unless we had an "internal server error" */
    if(response != 500)
      return((res == 0)&&(response == 200));

    retry--;
  }

  return FALSE;
}
コード例 #26
0
ファイル: dump.c プロジェクト: MasterDuke17/MoarVM
/* 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");
    }
}
コード例 #27
0
ファイル: dump.c プロジェクト: MasterDuke17/MoarVM
/* 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;
}
コード例 #28
0
void osm_upload(appdata_t *appdata, osm_t *osm, project_t *project) {

  printf("starting upload\n");

  /* upload config and confirmation dialog */

  /* count nodes */
  osm_dirty_t dirty;
  memset(&dirty, 0, sizeof(dirty));

  const node_t *node = osm->node;
  while(node) {
    object_counter(OSM_BASE(node), &dirty.nodes);
    node = node->next;
  }
  printf("nodes:     new %2d, dirty %2d, deleted %2d\n",
	 dirty.nodes.added, dirty.nodes.dirty, dirty.nodes.deleted);

  /* count ways */
  const way_t *way = osm->way;
  while(way) {
    object_counter(OSM_BASE(way), &dirty.ways);
    way = way->next;
  }
  printf("ways:      new %2d, dirty %2d, deleted %2d\n",
	 dirty.ways.added, dirty.ways.dirty, dirty.ways.deleted);

  /* count relations */
  const relation_t *relation = osm->relation;
  while(relation) {
    object_counter(OSM_BASE(relation), &dirty.relations);
    relation = relation->next;
  }
  printf("relations: new %2d, dirty %2d, deleted %2d\n",
	 dirty.relations.added, dirty.relations.dirty, dirty.relations.deleted);


  GtkWidget *dialog =
    misc_dialog_new(MISC_DIALOG_MEDIUM, _("Upload to OSM"),
		    GTK_WINDOW(appdata->window),
		    GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
		    GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
		    NULL);

  GtkWidget *table = gtk_table_new(4, 5, TRUE);

  table_attach_label_c(table, _("Total"),          1, 2, 0, 1);
  table_attach_label_c(table, _("New"),            2, 3, 0, 1);
  table_attach_label_c(table, _("Modified"),       3, 4, 0, 1);
  table_attach_label_c(table, _("Deleted"),        4, 5, 0, 1);

  int row = 1;
  table_attach_label_l(table, _("Nodes:"),         0, 1, row, row + 1);
  table_insert_count(table, &dirty.nodes, row++);

  table_attach_label_l(table, _("Ways:"),          0, 1, row, row + 1);
  table_insert_count(table, &dirty.ways, row++);

  table_attach_label_l(table, _("Relations:"),     0, 1, row, row + 1);
  table_insert_count(table, &dirty.relations, row++);

  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), table, FALSE, FALSE, 0);

  /* ------------------------------------------------------ */

  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
		     gtk_hseparator_new(), FALSE, FALSE, 0);

  /* ------- add username and password entries ------------ */

  table = gtk_table_new(2, 2, FALSE);
  table_attach_label_l(table, _("Username:"******"Password:"******"Please add a comment"), -1);

  /* disable ok button until user edited the comment */
  gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog),
				    GTK_RESPONSE_ACCEPT, FALSE);

  g_signal_connect(G_OBJECT(buffer), "changed",
		   G_CALLBACK(callback_buffer_modified), dialog);

#ifndef FREMANTLE
  GtkWidget *view = gtk_text_view_new_with_buffer(buffer);
#else
  GtkWidget *view = hildon_text_view_new();
  hildon_text_view_set_buffer(HILDON_TEXT_VIEW(view), buffer);
#endif

  gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(view), GTK_WRAP_WORD);
  gtk_text_view_set_editable(GTK_TEXT_VIEW(view), TRUE);
  gtk_text_view_set_left_margin(GTK_TEXT_VIEW(view), 2 );
  gtk_text_view_set_right_margin(GTK_TEXT_VIEW(view), 2 );

  g_object_set_data(G_OBJECT(view), "first_click", GINT_TO_POINTER(TRUE));
  g_signal_connect(G_OBJECT(view), "focus-in-event",
		   G_CALLBACK(cb_focus_in), buffer);


  gtk_container_add(GTK_CONTAINER(scrolled_win), view);

  gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox),
  			      scrolled_win);
  gtk_widget_show_all(dialog);

  if(GTK_RESPONSE_ACCEPT != gtk_dialog_run(GTK_DIALOG(dialog))) {
    printf("upload cancelled\n");
    gtk_widget_destroy(dialog);
    return;
  }

  printf("clicked ok\n");

  /* retrieve username and password */
  g_free(appdata->settings->username);
  appdata->settings->username =
    g_strdup(gtk_entry_get_text(GTK_ENTRY(uentry)));

  g_free(appdata->settings->password);
  appdata->settings->password =
    g_strdup(gtk_entry_get_text(GTK_ENTRY(pentry)));

  /* osm upload itself also has a gui */
  osm_upload_context_t *context = g_new0(osm_upload_context_t, 1);
  context->appdata = appdata;
  context->osm = osm;
  context->project = project;

  /* add proxy settings if required */
  if(appdata->settings)
    context->proxy = appdata->settings->proxy;

  /* fetch comment from dialog */
  GtkTextIter start, end;
  gtk_text_buffer_get_start_iter(buffer, &start);
  gtk_text_buffer_get_end_iter(buffer, &end);
  char *text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
  context->comment = g_strdup(text);

  gtk_widget_destroy(dialog);
  project_save(GTK_WIDGET(appdata->window), project);

  context->dialog =
    misc_dialog_new(MISC_DIALOG_LARGE,_("Uploading"),
	  GTK_WINDOW(appdata->window),
	  GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL);

  gtk_dialog_set_response_sensitive(GTK_DIALOG(context->dialog),
				    GTK_RESPONSE_CLOSE, FALSE);

  /* ------- main ui element is this text view --------------- */

  GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
  				 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);

  context->log.buffer = gtk_text_buffer_new(NULL);

  context->log.view = gtk_text_view_new_with_buffer(context->log.buffer);
  gtk_text_view_set_editable(GTK_TEXT_VIEW(context->log.view), FALSE);
  gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(context->log.view), FALSE);
  gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(context->log.view), GTK_WRAP_WORD);

  gtk_container_add(GTK_CONTAINER(scrolled_window), context->log.view);
  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window),
				      GTK_SHADOW_IN);

  gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(context->dialog)->vbox),
			       scrolled_window);
  gtk_widget_show_all(context->dialog);

  /* server url should not end with a slash */
  if(project->rserver && project->rserver[strlen(project->rserver)-1] == '/') {
    printf("removing trailing slash\n");
    project->rserver[strlen(project->rserver)-1] = 0;
  }

  appendf(&context->log, NULL, _("Log generated by %s v%s using API 0.6\n"),
	  PACKAGE, VERSION);
  appendf(&context->log, NULL, _("User comment: %s\n"), context->comment);

   /* check if server name contains string "0.5" and adjust it */
  if(project->rserver && strstr(project->rserver, "0.5") != NULL) {
    strstr(project->rserver, "0.5")[2] = '6';

    appendf(&context->log, NULL, _("Adjusting server name to v0.6\n"));
  }

  appendf(&context->log, NULL, _("Uploading to %s\n"), project->server);

  /* create a new changeset */
  gchar *cred;
  if(osm_create_changeset(context, &cred)) {
    /* check for dirty entries */
    appendf(&context->log, NULL, _("Uploading nodes:\n"));
    osm_upload_nodes(context, cred);
    appendf(&context->log, NULL, _("Uploading ways:\n"));
    osm_upload_ways(context, cred);
    appendf(&context->log, NULL, _("Uploading relations:\n"));
    osm_upload_relations(context, cred);
    appendf(&context->log, NULL, _("Deleting relations:\n"));
    osm_delete_relations(context, cred);
    appendf(&context->log, NULL, _("Deleting ways:\n"));
    osm_delete_ways(context, cred);
    appendf(&context->log, NULL, _("Deleting nodes:\n"));
    osm_delete_nodes(context, cred);

    /* close changeset */
    osm_close_changeset(context, cred);
  }

  appendf(&context->log, NULL, _("Upload done.\n"));

  gboolean reload_map = FALSE;
  if(project->data_dirty) {
    appendf(&context->log, NULL, _("Server data has been modified.\n"));
    appendf(&context->log, NULL, _("Downloading updated osm data ...\n"));

    if(osm_download(context->dialog, appdata->settings, project)) {
      appendf(&context->log, NULL, _("Download successful!\n"));
      appendf(&context->log, NULL, _("The map will be reloaded.\n"));
      project->data_dirty = FALSE;
      reload_map = TRUE;
    } else
      appendf(&context->log, NULL, _("Download failed!\n"));

    project_save(context->dialog, project);

    if(reload_map) {
      /* this kind of rather brute force reload is useful as the moment */
      /* after the upload is a nice moment to bring everything in sync again. */
      /* we basically restart the entire map with fresh data from the server */
      /* and the diff will hopefully be empty (if the upload was successful) */

      appendf(&context->log, NULL, _("Reloading map ...\n"));

      if(!diff_is_clean(appdata->osm, FALSE)) {
	appendf(&context->log, COLOR_ERR, _("*** DIFF IS NOT CLEAN ***\n"));
	appendf(&context->log, COLOR_ERR, _("Something went wrong during upload,\n"));
	appendf(&context->log, COLOR_ERR, _("proceed with care!\n"));
      }

      /* redraw the entire map by destroying all map items and redrawing them */
      appendf(&context->log, NULL, _("Cleaning up ...\n"));
      diff_save(appdata->project, appdata->osm);
      map_clear(appdata, MAP_LAYER_OBJECTS_ONLY);
      osm_free(appdata->osm);

      appendf(&context->log, NULL, _("Loading OSM ...\n"));
      appdata->osm = osm_parse(appdata->project->path, appdata->project->osm, &appdata->icon);
      appendf(&context->log, NULL, _("Applying diff ...\n"));
      diff_restore(appdata, appdata->project, appdata->osm);
      appendf(&context->log, NULL, _("Painting ...\n"));
      map_paint(appdata);
      appendf(&context->log, NULL, _("Done!\n"));
    }
  }

  /* tell the user that he can stop waiting ... */
  appendf(&context->log, NULL, _("Process finished.\n"));

  gtk_dialog_set_response_sensitive(GTK_DIALOG(context->dialog),
				    GTK_RESPONSE_CLOSE, TRUE);

  gtk_dialog_run(GTK_DIALOG(context->dialog));
  gtk_widget_destroy(context->dialog);

  g_free(context->comment);
  g_free(context);
}
コード例 #29
0
StrBuffer & StrBuffer::append(char c) 
{
    appendf("%c",c);
    return *this;
}
コード例 #30
0
ファイル: dump.c プロジェクト: MasterDuke17/MoarVM
/* Dumps the facts table. */
static void dump_facts(MVMThreadContext *tc, DumpStr *ds, MVMSpeshGraph *g) {
    MVMuint16 i, j, num_locals, num_facts;
    num_locals = g->num_locals;
    for (i = 0; i < num_locals; i++) {
        num_facts = g->fact_counts[i];
        for (j = 0; j < num_facts; j++) {
            MVMint32 flags = g->facts[i][j].flags;
            MVMSpeshOperand operand;
            operand.reg.orig = i;
            operand.reg.i = j;
            if (i < 10) append(ds, " ");
            if (j < 10) append(ds, " ");
            if (flags || g->facts[i][j].dead_writer || (g->facts[i][j].writer && g->facts[i][j].writer->info->opcode == MVM_SSA_PHI)) {
                appendf(ds, "    r%d(%d): usages=%d%s", i, j,
                    MVM_spesh_usages_count(tc, g, operand),
                    MVM_spesh_usages_is_used_by_handler(tc, g, operand) ? "+handler" : "");
                dump_deopt_usages(tc, ds, g, operand);
                appendf(ds, ", flags=%-5d", flags);
                if (flags & 1) {
                    append(ds, " KnTyp");
                }
                if (flags & 2) {
                    append(ds, " KnVal");
                }
                if (flags & 4) {
                    append(ds, " Dcntd");
                }
                if (flags & 8) {
                    append(ds, " Concr");
                }
                if (flags & 16) {
                    append(ds, " TyObj");
                }
                if (flags & 32) {
                    append(ds, " KnDcT");
                }
                if (flags & 64) {
                    append(ds, " DCncr");
                }
                if (flags & 128) {
                    append(ds, " DcTyO");
                }
                if (flags & 256) {
                    append(ds, " LogGd");
                }
                if (flags & 512) {
                    append(ds, " HashI");
                }
                if (flags & 1024) {
                    append(ds, " ArrIt");
                }
                if (flags & 2048) {
                    append(ds, " KBxSr");
                }
                if (flags & 4096) {
                    append(ds, " MgWLG");
                }
                if (flags & 8192) {
                    append(ds, " KRWCn");
                }
                if (g->facts[i][j].dead_writer) {
                    append(ds, " DeadWriter");
                }
                if (g->facts[i][j].writer && g->facts[i][j].writer->info->opcode == MVM_SSA_PHI) {
                    appendf(ds, " (merged from %d regs)", g->facts[i][j].writer->info->num_operands - 1);
                }
                if (flags & 1) {
                    appendf(ds, " (type: %s)", MVM_6model_get_debug_name(tc, g->facts[i][j].type));
                }
            }
            else {
                appendf(ds, "    r%d(%d): usages=%d%s", i, j,
                    MVM_spesh_usages_count(tc, g, operand),
                    MVM_spesh_usages_is_used_by_handler(tc, g, operand) ? "+handler" : "");
                dump_deopt_usages(tc, ds, g, operand);
                appendf(ds, ", flags=%-5d", flags);
            }
            append(ds, "\n");
        }
        append(ds, "\n");
    }
}