Files
sdk/runtime/vm/source_report.h
T
Tess Strickland 99a370942b [vm,dyn_modules] Update some coverage information for bytecode.
Add a flag to SourceFile which is true if the associated script
contains a list of covered const constructors, and serialize said
list if true.

Delay reading and resolving the list of covered const constructors in
the bytecode reader until code is read.

Update usage counters for interpreted functions in Entry instructions.

Fix up cases where SourceReport assumed compiled code as appropriate.

Remaining:
* Record call and assert coverage information if the current isolate
  group has coverage enabled.
* Record branch coverage information if the current isolate group
  has branch coverage enabled.

TEST=pkg/vm_service pkg/dart2bytecode

Cq-Include-Trybots: luci.dart.try:vm-dyn-linux-debug-x64-try,vm-aot-dyn-linux-debug-x64-try,vm-aot-dyn-linux-product-x64-try,vm-dyn-mac-debug-arm64-try
Change-Id: I14b6ffba1e175993e992c0fe939473557303bfeb
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/449900
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2025-10-01 09:51:59 -07:00

170 lines
5.8 KiB
C++

// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef RUNTIME_VM_SOURCE_REPORT_H_
#define RUNTIME_VM_SOURCE_REPORT_H_
#include "vm/globals.h"
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/allocation.h"
#include "vm/flags.h"
#include "vm/hash_map.h"
#include "vm/object.h"
#include "vm/profiler_service.h"
#include "vm/token_position.h"
namespace dart {
// A SourceReport object is used to generate reports about the program
// source code, with information associated with source token
// positions. There are multiple possible kinds of reports.
class SourceReport {
public:
enum ReportKind {
kCallSites = 0x1,
kCoverage = 0x2,
kPossibleBreakpoints = 0x4,
kProfile = 0x8,
kBranchCoverage = 0x10,
};
static const char* kCallSitesStr;
static const char* kCoverageStr;
static const char* kPossibleBreakpointsStr;
static const char* kProfileStr;
static const char* kBranchCoverageStr;
enum CompileMode { kNoCompile, kForceCompile };
// report_set is a bitvector indicating which reports to generate
// (e.g. kCallSites | kCoverage).
//
// If library_filters is not null, then the report will only include libraries
// whose URIs start with one of the filter strings.
explicit SourceReport(intptr_t report_set,
CompileMode compile = kNoCompile,
bool report_lines = false);
explicit SourceReport(intptr_t report_set,
const GrowableObjectArray& library_filters,
ZoneCStringSet* libraries_already_compiled = nullptr,
CompileMode compile = kNoCompile,
bool report_lines = false);
~SourceReport();
// Generate a source report for (some subrange of) a script.
//
// If script is null, then the report is generated for all scripts
// in the isolate.
void PrintJSON(JSONStream* js,
const Script& script,
TokenPosition start_pos = TokenPosition::kMinSource,
TokenPosition end_pos = TokenPosition::kMaxSource);
private:
void ClearScriptTable();
void Init(Thread* thread,
const Script* script,
TokenPosition start_pos,
TokenPosition end_pos);
Thread* thread() const { return thread_; }
Zone* zone() const { return thread_->zone(); }
Isolate* isolate() const { return thread_->isolate(); }
bool IsReportRequested(ReportKind report_kind);
bool ShouldSkipFunction(const Function& func);
bool ShouldSkipField(const Field& field);
intptr_t GetScriptIndex(const Script& script);
bool ScriptIsLoadedByLibrary(const Script& script, const Library& lib);
intptr_t GetTokenPosOrLine(const Script& script,
const TokenPosition& token_pos);
bool IsLibraryAlreadyCompiled(const Library& lib);
bool ShouldFiltersIncludeScript(const Script& script);
bool ShouldFiltersIncludeUrl(const String& url);
void PrintCallSitesData(JSONObject* jsobj,
const Function& func,
const Code& code);
void PrintCoverageData(JSONObject* jsobj,
intptr_t script_index,
const Function& func,
bool report_branch_coverage);
void PrintPossibleBreakpointsData(JSONObject* jsobj,
const Function& func,
const Code& code);
void PrintProfileData(JSONObject* jsobj, ProfileFunction* profile_function);
#if defined(DEBUG)
void VerifyScriptTable();
#endif
void PrintScriptTable(JSONArray* jsarr);
void VisitFunction(JSONArray* jsarr,
const Function& func,
CompileMode compile_mode);
void VisitField(JSONArray* jsarr,
const Field& field,
CompileMode compile_mode);
void VisitLibrary(JSONArray* jsarr, const Library& lib);
void VisitClosures(JSONArray* jsarr);
// An entry in the script table.
struct ScriptTableEntry {
ScriptTableEntry() : key(nullptr), index(-1), script(nullptr) {}
const String* key;
intptr_t index;
const Script* script;
GrowableArray<TokenPosition> const_constructor_hits;
};
// Needed for DirectChainedHashMap.
struct ScriptTableTrait {
typedef ScriptTableEntry* Value;
typedef const ScriptTableEntry* Key;
typedef ScriptTableEntry* Pair;
static Key KeyOf(Pair kv) { return kv; }
static Value ValueOf(Pair kv) { return kv; }
static inline uword Hash(Key key) { return key->key->Hash(); }
static inline bool IsKeyEqual(Pair kv, Key key) {
return kv->script->ptr() == key->script->ptr();
}
};
void CollectAllScripts(
DirectChainedHashMap<ScriptTableTrait>* local_script_table,
GrowableArray<ScriptTableEntry*>* local_script_table_entries);
void CleanupCollectedScripts(
DirectChainedHashMap<ScriptTableTrait>* local_script_table,
GrowableArray<ScriptTableEntry*>* local_script_table_entries);
void CollectConstConstructorCoverageFromScripts(
GrowableArray<ScriptTableEntry*>* local_script_table_entries);
intptr_t report_set_;
CompileMode compile_mode_;
bool report_lines_;
const GrowableObjectArray& library_filters_;
ZoneCStringSet* libraries_already_compiled_;
Thread* thread_;
const Script* script_;
TokenPosition start_pos_;
TokenPosition end_pos_;
Profile profile_;
GrowableArray<ScriptTableEntry*> script_table_entries_;
DirectChainedHashMap<ScriptTableTrait> script_table_;
intptr_t next_script_index_;
intptr_t late_error_class_id_ = ClassId::kIllegalCid;
};
} // namespace dart
#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
#endif // RUNTIME_VM_SOURCE_REPORT_H_