[cpu-profiler] Implement basic refcounting of CodeEntry strings

As a first step towards freeing CodeEntry objects that are neither still
referenced by JS or stored in a profile, enable freeing of refcounted
strings by CodeEntry instances. For now, this leaves behaviour unchanged
until we receive CodeEntry destruction events.

Bug: v8:11054
Change-Id: Iabd05aa730343cd1a879ff5b04326f23e68aa948
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2590604
Commit-Queue: Andrew Comminos <acomminos@fb.com>
Reviewed-by: Peter Marshall <petermarshall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71858}
This commit is contained in:
Andrew Comminos 2020-12-21 13:42:34 -08:00 committed by Commit Bot
parent a66bb00024
commit 20feaf9a00
11 changed files with 145 additions and 71 deletions

View File

@ -321,12 +321,17 @@ void* SamplingEventsProcessor::operator new(size_t size) {
void SamplingEventsProcessor::operator delete(void* ptr) { AlignedFree(ptr); }
ProfilerCodeObserver::ProfilerCodeObserver(Isolate* isolate)
: isolate_(isolate), processor_(nullptr) {
: isolate_(isolate), code_map_(strings_), processor_(nullptr) {
CreateEntriesForRuntimeCallStats();
LogBuiltins();
}
void ProfilerCodeObserver::ClearCodeMap() { code_map_.Clear(); }
void ProfilerCodeObserver::ClearCodeMap() {
code_map_.Clear();
// We don't currently expect any references to refcounted strings to be
// maintained with zero profiles after the code map is cleared.
DCHECK(strings_.empty());
}
void ProfilerCodeObserver::CodeEventHandler(
const CodeEventsContainer& evt_rec) {
@ -445,22 +450,24 @@ DEFINE_LAZY_LEAKY_OBJECT_GETTER(CpuProfilersManager, GetProfilersManager)
CpuProfiler::CpuProfiler(Isolate* isolate, CpuProfilingNamingMode naming_mode,
CpuProfilingLoggingMode logging_mode)
: CpuProfiler(isolate, naming_mode, logging_mode,
new CpuProfilesCollection(isolate), nullptr, nullptr) {}
new CpuProfilesCollection(isolate), nullptr, nullptr,
new ProfilerCodeObserver(isolate)) {}
CpuProfiler::CpuProfiler(Isolate* isolate, CpuProfilingNamingMode naming_mode,
CpuProfilingLoggingMode logging_mode,
CpuProfilesCollection* test_profiles,
Symbolizer* test_symbolizer,
ProfilerEventsProcessor* test_processor)
ProfilerEventsProcessor* test_processor,
ProfilerCodeObserver* test_code_observer)
: isolate_(isolate),
naming_mode_(naming_mode),
logging_mode_(logging_mode),
base_sampling_interval_(base::TimeDelta::FromMicroseconds(
FLAG_cpu_profiler_sampling_interval)),
code_observer_(test_code_observer),
profiles_(test_profiles),
symbolizer_(test_symbolizer),
processor_(test_processor),
code_observer_(isolate),
is_profiling_(false) {
profiles_->set_cpu_profiler(this);
GetProfilersManager()->AddProfiler(isolate, this);
@ -491,7 +498,7 @@ void CpuProfiler::ResetProfiles() {
symbolizer_.reset();
if (!profiling_scope_) {
profiler_listener_.reset();
code_observer_.ClearCodeMap();
code_observer_->ClearCodeMap();
}
}
@ -500,7 +507,8 @@ void CpuProfiler::EnableLogging() {
if (!profiler_listener_) {
profiler_listener_.reset(
new ProfilerListener(isolate_, &code_observer_, naming_mode_));
new ProfilerListener(isolate_, code_observer_.get(),
*code_observer_->strings(), naming_mode_));
}
profiling_scope_.reset(
new ProfilingScope(isolate_, profiler_listener_.get()));
@ -568,12 +576,12 @@ void CpuProfiler::StartProcessorIfNotStarted() {
}
if (!symbolizer_) {
symbolizer_ = std::make_unique<Symbolizer>(code_observer_.code_map());
symbolizer_ = std::make_unique<Symbolizer>(code_observer_->code_map());
}
base::TimeDelta sampling_interval = ComputeSamplingInterval();
processor_.reset(new SamplingEventsProcessor(
isolate_, symbolizer_.get(), &code_observer_, profiles_.get(),
isolate_, symbolizer_.get(), code_observer_.get(), profiles_.get(),
sampling_interval, use_precise_sampling_));
is_profiling_ = true;

View File

@ -236,16 +236,18 @@ class V8_EXPORT_PRIVATE SamplingEventsProcessor
// low sampling intervals on Windows.
};
// Builds and maintains a CodeMap tracking code objects on the VM heap. While
// alive, logs generated code, callbacks, and builtins from the isolate.
// Redirects events to the profiler events processor when present.
// Builds and maintains a CodeMap tracking code objects on the VM heap, as well
// as strings owned by them. While alive, logs generated code, callbacks, and
// builtins from the isolate. Redirects events to the profiler events
// processor when present.
class V8_EXPORT_PRIVATE ProfilerCodeObserver : public CodeEventObserver {
public:
explicit ProfilerCodeObserver(Isolate*);
void CodeEventHandler(const CodeEventsContainer& evt_rec) override;
CodeMap* code_map() { return &code_map_; }
StringsStorage* strings() { return &strings_; }
void ClearCodeMap();
private:
@ -267,6 +269,7 @@ class V8_EXPORT_PRIVATE ProfilerCodeObserver : public CodeEventObserver {
void clear_processor() { processor_ = nullptr; }
Isolate* const isolate_;
StringsStorage strings_;
CodeMap code_map_;
ProfilerEventsProcessor* processor_;
};
@ -299,7 +302,8 @@ class V8_EXPORT_PRIVATE CpuProfiler {
CpuProfiler(Isolate* isolate, CpuProfilingNamingMode naming_mode,
CpuProfilingLoggingMode logging_mode,
CpuProfilesCollection* profiles, Symbolizer* test_symbolizer,
ProfilerEventsProcessor* test_processor);
ProfilerEventsProcessor* test_processor,
ProfilerCodeObserver* test_code_observer);
~CpuProfiler();
CpuProfiler(const CpuProfiler&) = delete;
@ -337,7 +341,7 @@ class V8_EXPORT_PRIVATE CpuProfiler {
ProfilerListener* profiler_listener_for_test() const {
return profiler_listener_.get();
}
CodeMap* code_map_for_test() { return code_observer_.code_map(); }
CodeMap* code_map_for_test() { return code_observer_->code_map(); }
private:
void StartProcessorIfNotStarted();
@ -361,12 +365,12 @@ class V8_EXPORT_PRIVATE CpuProfiler {
// Sampling interval to which per-profile sampling intervals will be clamped
// to a multiple of, or used as the default if unspecified.
base::TimeDelta base_sampling_interval_;
std::unique_ptr<ProfilerCodeObserver> code_observer_;
std::unique_ptr<CpuProfilesCollection> profiles_;
std::unique_ptr<Symbolizer> symbolizer_;
std::unique_ptr<ProfilerEventsProcessor> processor_;
std::unique_ptr<ProfilerListener> profiler_listener_;
std::unique_ptr<ProfilingScope> profiling_scope_;
ProfilerCodeObserver code_observer_;
bool is_profiling_;
};

View File

@ -221,6 +221,25 @@ CodeEntry::RareData* CodeEntry::EnsureRareData() {
return rare_data_.get();
}
void CodeEntry::ReleaseStrings(StringsStorage& strings) {
if (name_) {
strings.Release(name_);
name_ = nullptr;
}
if (resource_name_) {
strings.Release(resource_name_);
resource_name_ = nullptr;
}
if (rare_data_) {
// All inline entries are exclusively owned by the CodeEntry. They'll be
// deallocated when the CodeEntry is deallocated.
for (auto& entry : rare_data_->inline_entries_) {
entry->ReleaseStrings(strings);
}
}
}
void CodeEntry::print() const {
base::OS::Print("CodeEntry: at %p\n", this);
@ -641,7 +660,8 @@ void CpuProfile::Print() const {
ProfilerStats::Instance()->Clear();
}
CodeMap::CodeMap() = default;
CodeMap::CodeMap(StringsStorage& function_and_resource_names)
: function_and_resource_names_(function_and_resource_names) {}
CodeMap::~CodeMap() { Clear(); }
@ -654,7 +674,12 @@ void CodeMap::Clear() {
code_entries_[free_slot].entry = nullptr;
free_slot = next_slot;
}
for (auto slot : code_entries_) delete slot.entry;
for (auto slot : code_entries_) {
if (slot.entry) {
slot.entry->ReleaseStrings(function_and_resource_names_);
delete slot.entry;
}
}
code_entries_.clear();
code_map_.clear();
@ -717,7 +742,10 @@ unsigned CodeMap::AddCodeEntry(Address start, CodeEntry* entry) {
}
void CodeMap::DeleteCodeEntry(unsigned index) {
delete code_entries_[index].entry;
auto* entry = code_entries_[index].entry;
entry->ReleaseStrings(function_and_resource_names_);
delete entry;
code_entries_[index].next_free_slot = free_list_head_;
free_list_head_ = index;
}

View File

@ -59,7 +59,8 @@ struct CodeEntryAndLineNumber;
class CodeEntry {
public:
// CodeEntry doesn't own name strings, just references them.
// CodeEntry may reference strings (|name|, |resource_name|) managed by a
// StringsStorage instance. These must be freed via ReleaseStrings.
inline CodeEntry(CodeEventListener::LogEventsAndTags tag, const char* name,
const char* resource_name = CodeEntry::kEmptyResourceName,
int line_number = v8::CpuProfileNode::kNoLineNumberInfo,
@ -163,6 +164,12 @@ class CodeEntry {
}
V8_INLINE static CodeEntry* root_entry() { return kRootEntry.Pointer(); }
// Releases strings owned by this CodeEntry, which may be allocated in the
// provided StringsStorage instance. This instance is not stored directly
// with the CodeEntry in order to reduce memory footprint.
// Called before every destruction.
void ReleaseStrings(StringsStorage& strings);
void print() const;
private:
@ -404,7 +411,9 @@ class CpuProfile {
class V8_EXPORT_PRIVATE CodeMap {
public:
CodeMap();
// Creates a new CodeMap with an associated StringsStorage to store the
// strings of CodeEntry objects within.
explicit CodeMap(StringsStorage& function_and_resource_names);
~CodeMap();
CodeMap(const CodeMap&) = delete;
CodeMap& operator=(const CodeMap&) = delete;
@ -439,6 +448,7 @@ class V8_EXPORT_PRIVATE CodeMap {
std::deque<CodeEntrySlotInfo> code_entries_;
std::map<Address, CodeEntryMapInfo> code_map_;
unsigned free_list_head_ = kNoFreeSlot;
StringsStorage& function_and_resource_names_;
};
class V8_EXPORT_PRIVATE CpuProfilesCollection {

View File

@ -25,8 +25,12 @@ namespace internal {
ProfilerListener::ProfilerListener(Isolate* isolate,
CodeEventObserver* observer,
StringsStorage& function_and_resource_names,
CpuProfilingNamingMode naming_mode)
: isolate_(isolate), observer_(observer), naming_mode_(naming_mode) {}
: isolate_(isolate),
observer_(observer),
function_and_resource_names_(function_and_resource_names),
naming_mode_(naming_mode) {}
ProfilerListener::~ProfilerListener() = default;
@ -78,9 +82,12 @@ namespace {
CodeEntry* GetOrInsertCachedEntry(
std::unordered_set<std::unique_ptr<CodeEntry>, CodeEntry::Hasher,
CodeEntry::Equals>* entries,
std::unique_ptr<CodeEntry> search_value) {
std::unique_ptr<CodeEntry> search_value, StringsStorage& strings) {
auto it = entries->find(search_value);
if (it != entries->end()) return it->get();
if (it != entries->end()) {
search_value->ReleaseStrings(strings);
return it->get();
}
CodeEntry* ret = search_value.get();
entries->insert(std::move(search_value));
return ret;
@ -168,7 +175,8 @@ void ProfilerListener::CodeCreateEvent(LogEventsAndTags tag,
// Create a canonical CodeEntry for each inlined frame and then re-use
// them for subsequent inline stacks to avoid a lot of duplication.
CodeEntry* cached_entry = GetOrInsertCachedEntry(
&cached_inline_entries, std::move(inline_entry));
&cached_inline_entries, std::move(inline_entry),
function_and_resource_names_);
inline_stack.push_back({cached_entry, line_number});
}

View File

@ -27,6 +27,7 @@ class CodeEventObserver {
class V8_EXPORT_PRIVATE ProfilerListener : public CodeEventListener {
public:
ProfilerListener(Isolate*, CodeEventObserver*,
StringsStorage& function_and_resource_names,
CpuProfilingNamingMode mode = kDebugNaming);
~ProfilerListener() override;
ProfilerListener(const ProfilerListener&) = delete;
@ -89,7 +90,7 @@ class V8_EXPORT_PRIVATE ProfilerListener : public CodeEventListener {
Isolate* isolate_;
CodeEventObserver* observer_;
StringsStorage function_and_resource_names_;
StringsStorage& function_and_resource_names_;
const CpuProfilingNamingMode naming_mode_;
};

View File

@ -49,6 +49,7 @@ const char* StringsStorage::GetFormatted(const char* format, ...) {
}
const char* StringsStorage::AddOrDisposeString(char* str, int len) {
base::MutexGuard guard(&mutex_);
base::HashMap::Entry* entry = GetEntry(str, len);
if (entry->value == nullptr) {
// New entry added.
@ -119,11 +120,15 @@ inline uint32_t ComputeStringHash(const char* str, int len) {
} // namespace
bool StringsStorage::Release(const char* str) {
base::MutexGuard guard(&mutex_);
int len = static_cast<int>(strlen(str));
uint32_t hash = ComputeStringHash(str, len);
base::HashMap::Entry* entry = names_.Lookup(const_cast<char*>(str), hash);
DCHECK(entry);
if (!entry) {
// If an entry wasn't found or the address of the found entry doesn't match
// the one passed in, this string wasn't managed by this StringsStorage
// instance (i.e. a constant). Ignore this.
if (!entry || entry->key != str) {
return false;
}

View File

@ -9,6 +9,7 @@
#include "src/base/compiler-specific.h"
#include "src/base/hashmap.h"
#include "src/base/platform/mutex.h"
#include "src/common/globals.h"
namespace v8 {
@ -38,13 +39,16 @@ class V8_EXPORT_PRIVATE StringsStorage {
// result.
const char* GetConsName(const char* prefix, Name name);
// Reduces the refcount of the given string, freeing it if no other
// references are made to it.
// Returns true if the string was successfully unref'd.
// references are made to it. Returns true if the string was successfully
// unref'd, or false if the string was not present in the table.
bool Release(const char* str);
// Returns the number of strings in the store.
size_t GetStringCountForTesting() const;
// Returns true if the strings table is empty.
bool empty() const { return names_.occupancy() == 0; }
private:
static bool StringsMatch(void* key1, void* key2);
// Adds the string to storage and returns it, or if a matching string exists
@ -55,6 +59,7 @@ class V8_EXPORT_PRIVATE StringsStorage {
const char* GetVFormatted(const char* format, va_list args);
base::CustomMatcherHashMap names_;
base::Mutex mutex_;
};
} // namespace internal

View File

@ -177,7 +177,8 @@ TEST(CodeEvents) {
isolate, symbolizer, &code_observer, profiles,
v8::base::TimeDelta::FromMicroseconds(100), true);
CHECK(processor->Start());
ProfilerListener profiler_listener(isolate, processor);
ProfilerListener profiler_listener(isolate, processor,
*code_observer.strings());
isolate->logger()->AddCodeEventListener(&profiler_listener);
// Enqueue code creation events.
@ -232,16 +233,17 @@ TEST(TickEvents) {
i::Handle<i::AbstractCode> frame3_code(CreateCode(isolate, &env), isolate);
CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
ProfilerCodeObserver code_observer(isolate);
Symbolizer* symbolizer = new Symbolizer(code_observer.code_map());
ProfilerCodeObserver* code_observer = new ProfilerCodeObserver(isolate);
Symbolizer* symbolizer = new Symbolizer(code_observer->code_map());
ProfilerEventsProcessor* processor = new SamplingEventsProcessor(
CcTest::i_isolate(), symbolizer, &code_observer, profiles,
CcTest::i_isolate(), symbolizer, code_observer, profiles,
v8::base::TimeDelta::FromMicroseconds(100), true);
CpuProfiler profiler(isolate, kDebugNaming, kLazyLogging, profiles,
symbolizer, processor);
symbolizer, processor, code_observer);
profiles->StartProfiling("");
CHECK(processor->Start());
ProfilerListener profiler_listener(isolate, processor);
ProfilerListener profiler_listener(isolate, processor,
*code_observer->strings());
isolate->logger()->AddCodeEventListener(&profiler_listener);
profiler_listener.CodeCreateEvent(i::Logger::BUILTIN_TAG, frame1_code, "bbb");
@ -392,16 +394,17 @@ TEST(Issue1398) {
i::Handle<i::AbstractCode> code(CreateCode(isolate, &env), isolate);
CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
ProfilerCodeObserver code_observer(isolate);
Symbolizer* symbolizer = new Symbolizer(code_observer.code_map());
ProfilerCodeObserver* code_observer = new ProfilerCodeObserver(isolate);
Symbolizer* symbolizer = new Symbolizer(code_observer->code_map());
ProfilerEventsProcessor* processor = new SamplingEventsProcessor(
CcTest::i_isolate(), symbolizer, &code_observer, profiles,
CcTest::i_isolate(), symbolizer, code_observer, profiles,
v8::base::TimeDelta::FromMicroseconds(100), true);
CpuProfiler profiler(isolate, kDebugNaming, kLazyLogging, profiles,
symbolizer, processor);
symbolizer, processor, code_observer);
profiles->StartProfiling("");
CHECK(processor->Start());
ProfilerListener profiler_listener(isolate, processor);
ProfilerListener profiler_listener(isolate, processor,
*code_observer->strings());
profiler_listener.CodeCreateEvent(i::Logger::BUILTIN_TAG, code, "bbb");
@ -1245,13 +1248,13 @@ static void TickLines(bool optimize) {
CHECK_NE(code_address, kNullAddress);
CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
ProfilerCodeObserver code_observer(isolate);
Symbolizer* symbolizer = new Symbolizer(code_observer.code_map());
ProfilerCodeObserver* code_observer = new ProfilerCodeObserver(isolate);
Symbolizer* symbolizer = new Symbolizer(code_observer->code_map());
ProfilerEventsProcessor* processor = new SamplingEventsProcessor(
CcTest::i_isolate(), symbolizer, &code_observer, profiles,
CcTest::i_isolate(), symbolizer, code_observer, profiles,
v8::base::TimeDelta::FromMicroseconds(100), true);
CpuProfiler profiler(isolate, kDebugNaming, kLazyLogging, profiles,
symbolizer, processor);
symbolizer, processor, code_observer);
profiles->StartProfiling("");
// TODO(delphick): Stop using the CpuProfiler internals here: This forces
// LogCompiledFunctions so that source positions are collected everywhere.
@ -1259,7 +1262,8 @@ static void TickLines(bool optimize) {
// but doesn't because it's constructed with a symbolizer and a processor.
isolate->logger()->LogCompiledFunctions();
CHECK(processor->Start());
ProfilerListener profiler_listener(isolate, processor);
ProfilerListener profiler_listener(isolate, processor,
*code_observer->strings());
// Enqueue code creation events.
i::Handle<i::String> str = factory->NewStringFromAsciiChecked(func_name);
@ -3549,14 +3553,14 @@ TEST(ProflilerSubsampling) {
i::HandleScope scope(isolate);
CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
ProfilerCodeObserver code_observer(isolate);
Symbolizer* symbolizer = new Symbolizer(code_observer.code_map());
ProfilerCodeObserver* code_observer = new ProfilerCodeObserver(isolate);
Symbolizer* symbolizer = new Symbolizer(code_observer->code_map());
ProfilerEventsProcessor* processor =
new SamplingEventsProcessor(isolate, symbolizer, &code_observer, profiles,
new SamplingEventsProcessor(isolate, symbolizer, code_observer, profiles,
v8::base::TimeDelta::FromMicroseconds(1),
/* use_precise_sampling */ true);
CpuProfiler profiler(isolate, kDebugNaming, kLazyLogging, profiles,
symbolizer, processor);
symbolizer, processor, code_observer);
// Create a new CpuProfile that wants samples at 8us.
CpuProfile profile(&profiler, "",
@ -3593,14 +3597,14 @@ TEST(DynamicResampling) {
i::HandleScope scope(isolate);
CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
ProfilerCodeObserver code_observer(isolate);
Symbolizer* symbolizer = new Symbolizer(code_observer.code_map());
ProfilerCodeObserver* code_observer = new ProfilerCodeObserver(isolate);
Symbolizer* symbolizer = new Symbolizer(code_observer->code_map());
ProfilerEventsProcessor* processor =
new SamplingEventsProcessor(isolate, symbolizer, &code_observer, profiles,
new SamplingEventsProcessor(isolate, symbolizer, code_observer, profiles,
v8::base::TimeDelta::FromMicroseconds(1),
/* use_precise_sampling */ true);
CpuProfiler profiler(isolate, kDebugNaming, kLazyLogging, profiles,
symbolizer, processor);
symbolizer, processor, code_observer);
// Set a 1us base sampling rate, dividing all possible intervals.
profiler.set_sampling_interval(base::TimeDelta::FromMicroseconds(1));
@ -3654,14 +3658,14 @@ TEST(DynamicResamplingWithBaseInterval) {
i::HandleScope scope(isolate);
CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
ProfilerCodeObserver code_observer(isolate);
Symbolizer* symbolizer = new Symbolizer(code_observer.code_map());
ProfilerCodeObserver* code_observer = new ProfilerCodeObserver(isolate);
Symbolizer* symbolizer = new Symbolizer(code_observer->code_map());
ProfilerEventsProcessor* processor =
new SamplingEventsProcessor(isolate, symbolizer, &code_observer, profiles,
new SamplingEventsProcessor(isolate, symbolizer, code_observer, profiles,
v8::base::TimeDelta::FromMicroseconds(1),
/* use_precise_sampling */ true);
CpuProfiler profiler(isolate, kDebugNaming, kLazyLogging, profiles,
symbolizer, processor);
symbolizer, processor, code_observer);
profiler.set_sampling_interval(base::TimeDelta::FromMicroseconds(7));

View File

@ -311,7 +311,8 @@ static inline i::Address ToAddress(int n) { return static_cast<i::Address>(n); }
static inline void* ToPointer(int n) { return reinterpret_cast<void*>(n); }
TEST(CodeMapAddCode) {
CodeMap code_map;
StringsStorage strings;
CodeMap code_map(strings);
CodeEntry* entry1 = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "aaa");
CodeEntry* entry2 = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "bbb");
CodeEntry* entry3 = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "ccc");
@ -340,7 +341,8 @@ TEST(CodeMapAddCode) {
}
TEST(CodeMapMoveAndDeleteCode) {
CodeMap code_map;
StringsStorage strings;
CodeMap code_map(strings);
CodeEntry* entry1 = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "aaa");
CodeEntry* entry2 = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "bbb");
code_map.AddCode(ToAddress(0x1500), entry1, 0x200);
@ -357,7 +359,8 @@ TEST(CodeMapMoveAndDeleteCode) {
}
TEST(CodeMapClear) {
CodeMap code_map;
StringsStorage strings;
CodeMap code_map(strings);
CodeEntry* entry1 = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "aaa");
CodeEntry* entry2 = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "bbb");
code_map.AddCode(ToAddress(0x1500), entry1, 0x200);
@ -392,7 +395,8 @@ class TestSetup {
TEST(SymbolizeTickSample) {
TestSetup test_setup;
CodeMap code_map;
StringsStorage strings;
CodeMap code_map(strings);
Symbolizer symbolizer(&code_map);
CodeEntry* entry1 = new CodeEntry(i::Logger::FUNCTION_TAG, "aaa");
CodeEntry* entry2 = new CodeEntry(i::Logger::FUNCTION_TAG, "bbb");
@ -460,7 +464,8 @@ TEST(SampleIds) {
CpuProfiler profiler(isolate);
profiles.set_cpu_profiler(&profiler);
profiles.StartProfiling("", {CpuProfilingMode::kLeafNodeLineNumbers});
CodeMap code_map;
StringsStorage strings;
CodeMap code_map(strings);
Symbolizer symbolizer(&code_map);
CodeEntry* entry1 = new CodeEntry(i::Logger::FUNCTION_TAG, "aaa");
CodeEntry* entry2 = new CodeEntry(i::Logger::FUNCTION_TAG, "bbb");
@ -525,7 +530,8 @@ TEST(NoSamples) {
CpuProfiler profiler(isolate);
profiles.set_cpu_profiler(&profiler);
profiles.StartProfiling("");
CodeMap code_map;
StringsStorage strings;
CodeMap code_map(strings);
Symbolizer symbolizer(&code_map);
CodeEntry* entry1 = new CodeEntry(i::Logger::FUNCTION_TAG, "aaa");
symbolizer.code_map()->AddCode(ToAddress(0x1500), entry1, 0x200);

View File

@ -141,20 +141,15 @@ TEST_F(StringsStorageWithIsolate, Refcounting) {
CHECK_EQ(storage.GetStringCountForTesting(), 1);
CHECK(storage.Release(d));
CHECK_EQ(storage.GetStringCountForTesting(), 0);
#if !DEBUG
CHECK(!storage.Release("12"));
#endif // !DEBUG
}
TEST_F(StringsStorageWithIsolate, InvalidRelease) {
StringsStorage storage;
// If a refcount becomes invalid, throw in debug builds.
#ifdef DEBUG
ASSERT_DEATH_IF_SUPPORTED(storage.Release("12"), "check failed");
#else
// If we attempt to release a string not being managed by the StringsStorage,
// return false.
CHECK(!storage.Release("12"));
#endif // DEBUG
}
TEST_F(StringsStorageWithIsolate, CopyAndConsShareStorage) {