/* Looks up a wval and adds information based on it. */ static void wval_facts(MVMThreadContext *tc, MVMSpeshGraph *g, MVMuint16 tgt_orig, MVMuint16 tgt_i, MVMuint16 dep, MVMint64 idx) { MVMCompUnit *cu = g->sf->body.cu; if (dep < cu->body.num_scs) { MVMSerializationContext *sc = MVM_sc_get_sc(tc, cu, dep); if (sc) object_facts(tc, g, tgt_orig, tgt_i, MVM_sc_get_object(tc, sc, idx)); } }
/* 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"); }