23 : block_ids_(n_blocks), counts_(n_blocks, 0) {}
51 int32_t false_block_id) {
52 branches_.emplace_back(true_block_id, false_block_id);
57 auto data = std::make_unique<BasicBlockProfilerData>(n_blocks);
66 return isolate->factory()->NewStringFromAsciiChecked(source.c_str(),
88 schedule_ = js_heap_data->schedule()->ToCString().get();
89 code_ = js_heap_data->code()->ToCString().get();
92 for (
int i = 0;
i <
counts->length() / kBlockCountSlotSize; ++
i) {
96 for (
int i = 0;
i < block_ids->length() / kBlockIdSlotSize; ++
i) {
100 js_heap_data->branches();
101 for (
int i = 0;
i < branches->length(); ++
i) {
105 hash_ = js_heap_data->hash();
110 int id_array_size_in_bytes =
static_cast<int>(
n_blocks() * kBlockIdSlotSize);
111 CHECK(id_array_size_in_bytes >= 0 &&
112 static_cast<size_t>(id_array_size_in_bytes) / kBlockIdSlotSize ==
116 for (
int i = 0; i < static_cast<int>(
n_blocks()); ++
i) {
120 int counts_array_size_in_bytes =
121 static_cast<int>(
n_blocks() * kBlockCountSlotSize);
122 CHECK(counts_array_size_in_bytes >= 0 &&
123 static_cast<size_t>(counts_array_size_in_bytes) / kBlockCountSlotSize ==
127 for (
int i = 0; i < static_cast<int>(
n_blocks()); ++
i) {
134 for (
int i = 0; i < static_cast<int>(
branches_.size()); ++
i) {
141 return isolate->factory()->NewOnHeapBasicBlockProfilerData(
153 for (
int i = 0;
i < list->length(); ++
i) {
156 for (
int j = 0; j < counts->length() / kBlockCountSlotSize; ++j) {
164 isolate->heap()->basic_block_profiling_data()->length() > 0;
168 os <<
"---- Start Profiling Data ----" <<
'\n';
175 std::unordered_set<std::string> builtin_names;
176 for (
int i = 0;
i < list->length(); ++
i) {
184 CHECK(builtin_names.insert(data.function_name_).second);
186 os <<
"---- End Profiling Data ----" <<
'\n';
193 std::unordered_set<std::string> builtin_names;
194 for (
int i = 0;
i < list->length(); ++
i) {
199 data.Log(isolate, os);
202 CHECK(builtin_names.insert(data.function_name_).second);
209 std::vector<bool> out;
210 int list_length = list->length();
211 for (
int i = 0;
i < list_length; ++
i) {
214 for (
size_t j = 0; j < data.n_blocks(); ++j) {
215 out.push_back(data.counts_[j] > 0);
222 bool any_nonzero_counter =
false;
223 constexpr char kNext[] =
"\t";
226 any_nonzero_counter =
true;
232 if (any_nonzero_counter) {
244 if (std::all_of(d.counts_.cbegin(), d.counts_.cend(),
245 [](uint32_t
count) { return count == 0; })) {
249 const char* name =
"unknown function";
250 if (!d.function_name_.empty()) {
251 name = d.function_name_.c_str();
253 if (!d.schedule_.empty()) {
254 os <<
"schedule for " << name <<
" (B0 entered " << d.counts_[0]
255 <<
" times)" <<
'\n';
256 os << d.schedule_.c_str() <<
'\n';
258 os <<
"block counts for " << name <<
":" <<
'\n';
259 std::vector<std::pair<size_t, uint32_t>>
pairs;
260 pairs.reserve(d.n_blocks());
261 for (
size_t i = 0;
i < d.n_blocks(); ++
i) {
262 pairs.push_back(std::make_pair(
i, d.counts_[
i]));
266 [=](std::pair<size_t, uint32_t> left, std::pair<size_t, uint32_t> right) {
267 if (right.second == left.second) return left.first < right.first;
268 return right.second < left.second;
270 for (
auto it :
pairs) {
271 if (it.second == 0)
break;
272 os <<
"block B" << it.first <<
" : " << it.second <<
'\n';
275 if (!d.code_.empty()) {
276 os << d.code_.c_str() <<
'\n';
289 if (callees.count(block_id) == 0) {
293 if (block_callees.count(callee) == 0) {
294 block_callees.emplace(callee);
union v8::internal::@341::BuiltinMetadata::KindSpecificData data
void SetFunctionName(std::unique_ptr< char[]> name)
DirectHandle< OnHeapBasicBlockProfilerData > CopyToJSHeap(Isolate *isolate)
const uint32_t * counts() const
std::vector< uint32_t > counts_
void SetCode(const std::ostringstream &os)
BasicBlockProfilerData(size_t n_blocks)
void SetBlockId(size_t offset, int32_t id)
std::vector< std::pair< int32_t, int32_t > > branches_
void CopyFromJSHeap(Tagged< OnHeapBasicBlockProfilerData > js_heap_data)
std::string function_name_
void SetSchedule(const std::ostringstream &os)
void AddBranch(int32_t true_block_id, int32_t false_block_id)
void Log(Isolate *isolate, std::ostream &os)
V8_EXPORT_PRIVATE void ResetCounts()
std::vector< int32_t > block_ids_
V8_EXPORT_PRIVATE bool HasData(Isolate *isolate)
static V8_EXPORT_PRIVATE BasicBlockProfiler * Get()
BasicBlockProfilerData * NewData(size_t n_blocks)
base::Mutex data_list_mutex_
V8_EXPORT_PRIVATE void Log(Isolate *isolate, std::ostream &os)
V8_EXPORT_PRIVATE std::vector< bool > GetCoverageBitmap(Isolate *isolate)
V8_EXPORT_PRIVATE void ResetCounts(Isolate *isolate)
V8_EXPORT_PRIVATE void Print(Isolate *isolate, std::ostream &os)
const BuiltinCallees * GetBuiltinCallees(Builtin builtin)
BuiltinCallMap builtin_call_map_
void AddBuiltinCall(Builtin caller, Builtin callee, int32_t block_id)
static BuiltinsCallGraph * Get()
static Handle< FixedIntegerArrayBase< T, Base > > New(Isolate *isolate, int length, MoreArgs &&... more_args)
#define DEFINE_LAZY_LEAKY_OBJECT_GETTER(T, FunctionName,...)
static constexpr char kBuiltinHashMarker[]
static constexpr char kBlockCounterMarker[]
static constexpr char kBlockHintMarker[]
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
std::ostream & operator<<(std::ostream &os, AtomicMemoryOrder order)
std::set< Builtin > BlockCallees
std::unordered_map< int32_t, BlockCallees > BuiltinCallees
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)