fix code coverage

This commit is contained in:
sfja 2024-12-16 18:23:51 +01:00
parent 1760913909
commit f8b573c135
6 changed files with 122 additions and 45 deletions

View File

@ -0,0 +1,52 @@
#include "arch.hpp"
#include "vm.hpp"
using namespace sliger;
size_t VM::instruction_size(size_t i) const
{
switch (static_cast<Op>(this->program.at(i))) {
case Op::Nop:
case Op::PushNull:
return 1;
case Op::PushInt:
case Op::PushBool:
return 2;
case Op::PushString: {
auto string_length = this->program.at(i + 1);
return 2 + string_length;
}
case Op::PushPtr:
return 2;
case Op::Pop:
return 1;
case Op::ReserveStatic:
case Op::LoadStatic:
case Op::StoreStatic:
case Op::LoadLocal:
case Op::StoreLocal:
case Op::Call:
return 2;
case Op::Return:
case Op::Jump:
case Op::JumpIfTrue:
return 1;
case Op::Builtin:
return 2;
case Op::Add:
case Op::Subtract:
case Op::Multiply:
case Op::Divide:
case Op::Remainder:
case Op::Equal:
case Op::LessThan:
case Op::And:
case Op::Or:
case Op::Xor:
case Op::Not:
return 1;
case Op::SourceMap:
return 4;
}
return 1;
}

View File

@ -451,7 +451,8 @@ void VM::run_file_builtin(Builtin builtin_id)
auto filename = stack_pop().as_string().value;
FILE* fp = std::fopen(filename.c_str(), mode.c_str());
if (fp == nullptr) {
std::cerr << std::format("error: could not open file '{}'\n", filename);
std::cerr << std::format(
"error: could not open file '{}'\n", filename);
std::exit(1);
}
auto file_id = this->file_id_counter;
@ -568,6 +569,14 @@ auto VM::stack_repr_string(size_t max_items) const -> std::string
return result;
};
void VM::assert_program_has(size_t count)
{
if (this->pc + count > program.size()) {
std::cerr << std::format("malformed program, pc = {}", this->pc);
std::exit(1);
}
}
void VM::assert_fn_stack_has(size_t count)
{
if (this->stack.size() - this->bp < count) {
@ -583,11 +592,3 @@ void VM::assert_stack_has(size_t count)
std::exit(1);
}
}
void VM::assert_program_has(size_t count)
{
if (this->pc + count > program.size()) {
std::cerr << std::format("malformed program, pc = {}", this->pc);
std::exit(1);
}
}

View File

@ -8,6 +8,7 @@
#include <cstdint>
#include <cstdio>
#include <string>
#include <utility>
#include <vector>
namespace sliger {
@ -108,6 +109,11 @@ struct CCPosEntry {
class CodeCoverageBuilder : public json::ToAndFromJson {
public:
inline void make_sure_entry_exists(SourcePos pos)
{
find_or_create_entry(pos);
}
/// call when leaving a source location
inline void report_cover(SourcePos pos)
{
@ -166,8 +172,19 @@ public:
return json::to_json(this->flame_graph);
}
inline auto code_coverage_json() const -> std::string
inline auto code_coverage_json() -> std::string
{
for (size_t i = 0; i < this->program.size(); ++i) {
if (this->program.at(i) == std::to_underlying(Op::SourceMap)
&& this->program.size() - 1 - i >= 3) {
auto index = static_cast<int32_t>(this->program.at(i + 1));
auto line = static_cast<int32_t>(this->program.at(i + 2));
auto col = static_cast<int32_t>(this->program.at(i + 3));
this->code_coverage.make_sure_entry_exists(
{ index, line, col });
}
i += instruction_size(i);
}
return json::to_json(this->code_coverage);
}
@ -223,6 +240,7 @@ private:
{
return this->stack.at(this->bp + idx);
}
void assert_program_has(size_t count);
void assert_fn_stack_has(size_t count);
void assert_stack_has(size_t count);
inline void stack_push(Value&& value) { this->stack.push_back(value); }
@ -233,7 +251,7 @@ private:
this->stack.pop_back();
return value;
}
void assert_program_has(size_t count);
size_t instruction_size(size_t i) const;
VMOpts opts;
uint32_t pc = 0;

View File

@ -97,21 +97,6 @@ export function loadCodeCoverage(
elements.push(span);
col += 1;
}
function positionInBox(
position: [number, number],
boundingRect: {
left: number;
top: number;
right: number;
bottom: number;
},
) {
const [x, y] = position;
const outside = x < boundingRect.left ||
x >= boundingRect.right || y < boundingRect.top ||
y >= boundingRect.bottom;
return !outside;
}
container.append(...elements);
document.addEventListener("mousemove", (event) => {
const [x, y] = [event.clientX, event.clientY];
@ -146,3 +131,19 @@ export function loadCodeCoverage(
});
return container;
}
function positionInBox(
position: [number, number],
boundingRect: {
left: number;
top: number;
right: number;
bottom: number;
},
) {
const [x, y] = position;
const outside = x < boundingRect.left ||
x >= boundingRect.right || y < boundingRect.top ||
y >= boundingRect.bottom;
return !outside;
}

View File

@ -57,15 +57,6 @@ function sourceCode(view: Element, codeData: string) {
view.replaceChildren(outerContainer);
}
async function codeCoverage(view: Element, codeData: string) {
const codeCoverageData = await data.codeCoverageData();
const outerContainer = document.createElement("div");
outerContainer.classList.add("code-container");
const innerContainer = document.createElement("div");
innerContainer.classList.add("code-container-inner");
function createRadio(
id: string,
content: string,
@ -85,6 +76,16 @@ async function codeCoverage(view: Element, codeData: string) {
container.append(input, label);
return [container, input];
}
async function codeCoverage(view: Element, codeData: string) {
const codeCoverageData = await data.codeCoverageData();
const outerContainer = document.createElement("div");
outerContainer.classList.add("code-container");
const innerContainer = document.createElement("div");
innerContainer.classList.add("code-container-inner");
const [perfGroup, perfInput] = createRadio(
"performance-coverage",
"Performance view",

View File

@ -159,6 +159,7 @@ main #cover {
.coverage-radio {
display: flex;
flex-direction: row;
justify-content: center;
}
.coverage-radio-group {
@ -166,6 +167,7 @@ main #cover {
justify-content: center;
flex: 1;
padding: 2rem;
max-width: max-content;
}
.coverage-radio-group label {
@ -173,6 +175,8 @@ main #cover {
border-radius: 0.25rem;
cursor: pointer;
border: 2px solid var(--code-status);
width: 280px;
text-align: center;
}
.coverage-radio-group input:checked ~ label {