luau/CLI/Coverage.cpp
Arseny Kapoulkine f2e6a8f4a5
Sync to upstream/release/507-pre (#286)
This doesn't contain all changes for 507 yet but we might want to do the
Luau 0.507 release a bit earlier to end the year sooner.

Changes:

- Type ascription (::) now permits casts between related types in both directions, allowing to refine or loosen the type (RFC #56)
- Fix type definition for tonumber to return number? since the input string isn't guaranteed to contain a valid number
- Fix type refinements for field access via []
- Many stability fixes for type checker
- Provide extra information in error messages for type mismatches in more cases
- Improve performance of type checking for large unions when union members are string literals
- Add coverage reporting support to Repl (--coverage command line argument) and lua_getcoverage C API
- Work around code signing issues during Makefile builds on macOS
- Improve performance of truthiness checks in some cases, particularly on Apple M1, resulting in 10-25% perf gains on qsort benchmark depending on the CPU/compiler
- Fix support for little-endian systems; IBM s390x here we go!
2021-12-10 14:05:05 -08:00

89 lines
1.9 KiB
C++

// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#include "Coverage.h"
#include "lua.h"
#include <string>
#include <vector>
struct Coverage
{
lua_State* L = nullptr;
std::vector<int> functions;
} gCoverage;
void coverageInit(lua_State* L)
{
gCoverage.L = lua_mainthread(L);
}
bool coverageActive()
{
return gCoverage.L != nullptr;
}
void coverageTrack(lua_State* L, int funcindex)
{
int ref = lua_ref(L, funcindex);
gCoverage.functions.push_back(ref);
}
static void coverageCallback(void* context, const char* function, int linedefined, int depth, const int* hits, size_t size)
{
FILE* f = static_cast<FILE*>(context);
std::string name;
if (depth == 0)
name = "<main>";
else if (function)
name = std::string(function) + ":" + std::to_string(linedefined);
else
name = "<anonymous>:" + std::to_string(linedefined);
fprintf(f, "FN:%d,%s\n", linedefined, name.c_str());
for (size_t i = 0; i < size; ++i)
if (hits[i] != -1)
{
fprintf(f, "FNDA:%d,%s\n", hits[i], name.c_str());
break;
}
for (size_t i = 0; i < size; ++i)
if (hits[i] != -1)
fprintf(f, "DA:%d,%d\n", int(i), hits[i]);
}
void coverageDump(const char* path)
{
lua_State* L = gCoverage.L;
FILE* f = fopen(path, "w");
if (!f)
{
fprintf(stderr, "Error opening coverage %s\n", path);
return;
}
fprintf(f, "TN:\n");
for (int fref: gCoverage.functions)
{
lua_getref(L, fref);
lua_Debug ar = {};
lua_getinfo(L, -1, "s", &ar);
fprintf(f, "SF:%s\n", ar.short_src);
lua_getcoverage(L, -1, f, coverageCallback);
fprintf(f, "end_of_record\n");
lua_pop(L, 1);
}
fclose(f);
printf("Coverage dump written to %s (%d functions)\n", path, int(gCoverage.functions.size()));
}