std::pair<size_t, bool> StreamWriter<StreamType>::append_value(const Value& v) { std::pair<size_t, bool> k(0, false); if(v.isNull()) k = append_null(); else if(v.isBool()) k = append_bool(v); else if(v.isChar()) k = append_char(v); else if(v.isSignedInteger()) k = append_signedInt(v); else if(v.isUnsignedInteger()) k = append_unsignedInt(v); else if(v.isFloat()) k = append_float(v); else if(v.isString()) k = append_string(v); //else if(v.isBinary()) // k = append_binary(v); //currently not supported else if(v.isArray()) k = append_array(v); else if(v.isObject()) k = append_object(v); return k; }
/* 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 = 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, ")\n\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; } append(&ds, "\n"); append_null(&ds); return ds.buffer; }
/* 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; }
/* 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; }
/* 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; }
/* 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; }
/* 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; }