* Populate bytecode panel with instruction data * @param {HTMLElement} panel - The panel element to populate * @param {HTMLElement} button - The button containing the bytecode data
(panel, button)
| 529 | * @param {HTMLElement} button - The button containing the bytecode data |
| 530 | */ |
| 531 | function populateBytecodePanel(panel, button) { |
| 532 | const bytecodeJson = button.getAttribute('data-bytecode'); |
| 533 | if (!bytecodeJson) return; |
| 534 | |
| 535 | // Get line number from parent |
| 536 | const lineDiv = button.closest('.code-line'); |
| 537 | const lineNum = lineDiv ? lineDiv.id.replace('line-', '') : null; |
| 538 | |
| 539 | try { |
| 540 | const instructions = JSON.parse(bytecodeJson); |
| 541 | if (!instructions.length) { |
| 542 | panel.innerHTML = '<div class="bytecode-empty">No bytecode data</div>'; |
| 543 | panel.dataset.populated = 'true'; |
| 544 | return; |
| 545 | } |
| 546 | |
| 547 | const maxSamples = Math.max(...instructions.map(i => i.samples), 1); |
| 548 | |
| 549 | // Calculate specialization stats |
| 550 | const totalSamples = instructions.reduce((sum, i) => sum + i.samples, 0); |
| 551 | const specializedSamples = instructions |
| 552 | .filter(i => i.is_specialized) |
| 553 | .reduce((sum, i) => sum + i.samples, 0); |
| 554 | const specPct = totalSamples > 0 ? Math.round(100 * specializedSamples / totalSamples) : 0; |
| 555 | const specializedCount = instructions.filter(i => i.is_specialized).length; |
| 556 | |
| 557 | // Determine specialization level class |
| 558 | let specClass = 'low'; |
| 559 | if (specPct >= 67) specClass = 'high'; |
| 560 | else if (specPct >= 33) specClass = 'medium'; |
| 561 | |
| 562 | // Build specialization summary |
| 563 | const instruction_word = instructions.length === 1 ? 'instruction' : 'instructions'; |
| 564 | const sample_word = totalSamples === 1 ? 'sample' : 'samples'; |
| 565 | let html = `<div class="bytecode-spec-summary ${specClass}"> |
| 566 | <span class="spec-pct">${specPct}%</span> |
| 567 | <span class="spec-label">specialized</span> |
| 568 | <span class="spec-detail">(${specializedCount}/${instructions.length} ${instruction_word}, ${specializedSamples.toLocaleString()}/${totalSamples.toLocaleString()} ${sample_word})</span> |
| 569 | </div>`; |
| 570 | |
| 571 | html += '<div class="bytecode-header">' + |
| 572 | '<span class="bytecode-opname">Instruction</span>' + |
| 573 | '<span class="bytecode-samples">Samples</span>' + |
| 574 | '<span>Heat</span></div>'; |
| 575 | |
| 576 | for (const instr of instructions) { |
| 577 | const heatPct = (instr.samples / maxSamples) * 100; |
| 578 | const isHot = heatPct > 50; |
| 579 | const specializedClass = instr.is_specialized ? ' specialized' : ''; |
| 580 | const baseOpHtml = instr.is_specialized |
| 581 | ? `<span class="base-op">(${escapeHtml(instr.base_opname)})</span>` : ''; |
| 582 | const badge = instr.is_specialized |
| 583 | ? '<span class="specialization-badge">SPECIALIZED</span>' : ''; |
| 584 | |
| 585 | // Build location data attributes for cross-referencing with source spans |
| 586 | const hasLocations = instr.locations && instr.locations.length > 0; |
| 587 | const locationData = hasLocations |
| 588 | ? `data-locations='${JSON.stringify(instr.locations)}' data-line="${lineNum}" data-opcode="${instr.opcode}"` |
no test coverage detected
searching dependent graphs…