mirror of
				https://git.sfja.dk/Mikkel/slige.git
				synced 2025-11-04 11:18:21 +00:00 
			
		
		
		
	fix code coverage
This commit is contained in:
		
							parent
							
								
									1760913909
								
							
						
					
					
						commit
						f8b573c135
					
				
							
								
								
									
										52
									
								
								runtime/instruction_size.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								runtime/instruction_size.cpp
									
									
									
									
									
										Normal 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;
 | 
			
		||||
}
 | 
			
		||||
@ -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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -57,6 +57,26 @@ function sourceCode(view: Element, codeData: string) {
 | 
			
		||||
    view.replaceChildren(outerContainer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function createRadio(
 | 
			
		||||
    id: string,
 | 
			
		||||
    content: string,
 | 
			
		||||
    checked: boolean,
 | 
			
		||||
): [HTMLDivElement, HTMLInputElement] {
 | 
			
		||||
    const label = document.createElement("label");
 | 
			
		||||
    label.htmlFor = id;
 | 
			
		||||
    label.innerText = content;
 | 
			
		||||
    const input = document.createElement("input");
 | 
			
		||||
    input.id = id;
 | 
			
		||||
    input.name = "coverage-radio";
 | 
			
		||||
    input.type = "radio";
 | 
			
		||||
    input.hidden = true;
 | 
			
		||||
    input.checked = checked;
 | 
			
		||||
    const container = document.createElement("div");
 | 
			
		||||
    container.classList.add("coverage-radio-group");
 | 
			
		||||
    container.append(input, label);
 | 
			
		||||
    return [container, input];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function codeCoverage(view: Element, codeData: string) {
 | 
			
		||||
    const codeCoverageData = await data.codeCoverageData();
 | 
			
		||||
 | 
			
		||||
@ -66,25 +86,6 @@ async function codeCoverage(view: Element, codeData: string) {
 | 
			
		||||
    const innerContainer = document.createElement("div");
 | 
			
		||||
    innerContainer.classList.add("code-container-inner");
 | 
			
		||||
 | 
			
		||||
    function createRadio(
 | 
			
		||||
        id: string,
 | 
			
		||||
        content: string,
 | 
			
		||||
        checked: boolean,
 | 
			
		||||
    ): [HTMLDivElement, HTMLInputElement] {
 | 
			
		||||
        const label = document.createElement("label");
 | 
			
		||||
        label.htmlFor = id;
 | 
			
		||||
        label.innerText = content;
 | 
			
		||||
        const input = document.createElement("input");
 | 
			
		||||
        input.id = id;
 | 
			
		||||
        input.name = "coverage-radio";
 | 
			
		||||
        input.type = "radio";
 | 
			
		||||
        input.hidden = true;
 | 
			
		||||
        input.checked = checked;
 | 
			
		||||
        const container = document.createElement("div");
 | 
			
		||||
        container.classList.add("coverage-radio-group");
 | 
			
		||||
        container.append(input, label);
 | 
			
		||||
        return [container, input];
 | 
			
		||||
    }
 | 
			
		||||
    const [perfGroup, perfInput] = createRadio(
 | 
			
		||||
        "performance-coverage",
 | 
			
		||||
        "Performance view",
 | 
			
		||||
 | 
			
		||||
@ -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 {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user