mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-11-02 20:47:33 +09:00
177 lines
5.2 KiB
C++
177 lines
5.2 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef vm_CodeCoverage_h
|
|
#define vm_CodeCoverage_h
|
|
|
|
#include "mozilla/Vector.h"
|
|
|
|
#include "ds/LifoAlloc.h"
|
|
|
|
#include "vm/Printer.h"
|
|
|
|
struct JSCompartment;
|
|
class JSScript;
|
|
class JSObject;
|
|
|
|
namespace js {
|
|
|
|
class ScriptSourceObject;
|
|
|
|
namespace coverage {
|
|
|
|
class LCovCompartment;
|
|
|
|
class LCovSource
|
|
{
|
|
public:
|
|
explicit LCovSource(LifoAlloc* alloc, JSObject* sso);
|
|
|
|
// Whether the given script source object matches this LCovSource.
|
|
bool match(JSObject* sso) const {
|
|
return sso == source_;
|
|
}
|
|
|
|
// Whether the current source is complete and if it can be flushed.
|
|
bool isComplete() const {
|
|
return hasFilename_ && hasTopLevelScript_;
|
|
}
|
|
|
|
// Iterate over the bytecode and collect the lcov output based on the
|
|
// ScriptCounts counters.
|
|
bool writeScript(JSScript* script);
|
|
|
|
// Write the Lcov output in a buffer, such as the one associated with
|
|
// the runtime code coverage trace file.
|
|
void exportInto(GenericPrinter& out) const;
|
|
|
|
// Write the script name in out.
|
|
bool writeSourceFilename(ScriptSourceObject* sso);
|
|
|
|
private:
|
|
// Write the script name in out.
|
|
bool writeScriptName(LSprinter& out, JSScript* script);
|
|
|
|
private:
|
|
// Weak pointer of the Script Source Object used by the current source.
|
|
JSObject *source_;
|
|
|
|
// LifoAlloc string which hold the filename of the source.
|
|
LSprinter outSF_;
|
|
|
|
// LifoAlloc strings which hold the filename of each function as
|
|
// well as the number of hits for each function.
|
|
LSprinter outFN_;
|
|
LSprinter outFNDA_;
|
|
size_t numFunctionsFound_;
|
|
size_t numFunctionsHit_;
|
|
|
|
// LifoAlloc string which hold branches statistics.
|
|
LSprinter outBRDA_;
|
|
size_t numBranchesFound_;
|
|
size_t numBranchesHit_;
|
|
|
|
// LifoAlloc string which hold lines statistics.
|
|
LSprinter outDA_;
|
|
size_t numLinesInstrumented_;
|
|
size_t numLinesHit_;
|
|
|
|
// Status flags.
|
|
bool hasFilename_ : 1;
|
|
bool hasTopLevelScript_ : 1;
|
|
};
|
|
|
|
class LCovCompartment
|
|
{
|
|
public:
|
|
LCovCompartment();
|
|
|
|
// Collect code coverage information for the given source.
|
|
void collectCodeCoverageInfo(JSCompartment* comp, JSObject* sso, JSScript* topLevel);
|
|
|
|
// Create an ebtry for the current ScriptSourceObject.
|
|
void collectSourceFile(JSCompartment* comp, ScriptSourceObject* sso);
|
|
|
|
// Write the Lcov output in a buffer, such as the one associated with
|
|
// the runtime code coverage trace file.
|
|
void exportInto(GenericPrinter& out, bool* isEmpty) const;
|
|
|
|
private:
|
|
// Write the script name in out.
|
|
bool writeCompartmentName(JSCompartment* comp);
|
|
|
|
// Return the LCovSource entry which matches the given ScriptSourceObject.
|
|
LCovSource* lookupOrAdd(JSCompartment* comp, JSObject* sso);
|
|
|
|
private:
|
|
typedef mozilla::Vector<LCovSource, 16, LifoAllocPolicy<Fallible>> LCovSourceVector;
|
|
|
|
// LifoAlloc backend for all temporary allocations needed to stash the
|
|
// strings to be written in the file.
|
|
LifoAlloc alloc_;
|
|
|
|
// LifoAlloc string which hold the name of the compartment.
|
|
LSprinter outTN_;
|
|
|
|
// Vector of all sources which are used in this compartment.
|
|
LCovSourceVector* sources_;
|
|
};
|
|
|
|
class LCovRuntime
|
|
{
|
|
public:
|
|
LCovRuntime();
|
|
~LCovRuntime();
|
|
|
|
// If the environment variable JS_CODE_COVERAGE_OUTPUT_DIR is set to a
|
|
// directory, create a file inside this directory which uses the process
|
|
// ID, the thread ID and a timestamp to ensure the uniqueness of the
|
|
// file.
|
|
//
|
|
// At the end of the execution, this file should contains the LCOV output of
|
|
// all the scripts executed in the current JSRuntime.
|
|
void init();
|
|
|
|
// Check if we should collect code coverage information.
|
|
bool isEnabled() const { return out_.isInitialized(); }
|
|
|
|
// Write the aggregated result of the code coverage of a compartment
|
|
// into a file.
|
|
void writeLCovResult(LCovCompartment& comp);
|
|
|
|
private:
|
|
// When a process forks, the file will remain open, but 2 processes will
|
|
// have the same file. To avoid conflicting writes, we open a new file for
|
|
// the child process.
|
|
void maybeReopenAfterFork();
|
|
|
|
// Fill an array with the name of the file. Return false if we are unable to
|
|
// serialize the filename in this array.
|
|
bool fillWithFilename(char *name, size_t length);
|
|
|
|
// Finish the current opened file, and remove if it does not have any
|
|
// content.
|
|
void finishFile();
|
|
|
|
private:
|
|
// Output file which is created if code coverage is enabled.
|
|
Fprinter out_;
|
|
|
|
// The process' PID is used to watch for fork. When the process fork,
|
|
// we want to close the current file and open a new one.
|
|
size_t pid_;
|
|
|
|
// Flag used to report if the generated file is empty or not. If it is empty
|
|
// when the runtime is destroyed, then the file would be removed as an empty
|
|
// file is not a valid LCov file.
|
|
bool isEmpty_;
|
|
};
|
|
|
|
} // namespace coverage
|
|
} // namespace js
|
|
|
|
#endif // vm_Printer_h
|
|
|