diff --git a/include/v8-profiler.h b/include/v8-profiler.h index 182b8d664cb..007ae2eca55 100644 --- a/include/v8-profiler.h +++ b/include/v8-profiler.h @@ -80,11 +80,6 @@ class V8_EXPORT CpuProfileNode { */ int GetColumnNumber() const; - /** - * Returns source line connected with current ProfileNode - */ - int GetSrcLine() const; - /** * Returns the number of the function's source lines that collect the samples. */ @@ -178,18 +173,6 @@ class V8_EXPORT CpuProfile { void Delete(); }; -/** - * HeapEventXDK contains the latest chunk of heap info - */ -class V8_EXPORT HeapEventXDK { - public: - const char* getSymbols(); - const char* getFrames(); - const char* getTypes(); - const char* getChunks(); - const char* getRetentions(); - unsigned int getDuration(); -}; /** * Interface for controlling CPU profiling. Instance of the @@ -358,18 +341,6 @@ class V8_EXPORT OutputStream { // NOLINT virtual WriteResult WriteHeapStatsChunk(HeapStatsUpdate* data, int count) { return kAbort; } - - /** - * Writes XDK object - */ - virtual WriteResult WriteHeapXDKChunk(const char* symbols, size_t symbolsSize, - const char* frames, size_t framesSize, - const char* types, size_t typesSize, - const char* chunks, size_t chunksSize, - const char* retentions, - size_t retentionSize) { - return kAbort; - } }; @@ -710,14 +681,6 @@ class V8_EXPORT HeapProfiler { */ void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info); - void StartTrackingHeapObjectsXDK(int stackDepth, bool retentions, - bool strict_collection = false); - /** - * @author amalyshe - */ - void GetHeapXDKStats(OutputStream* stream); - HeapEventXDK* StopTrackingHeapObjectsXDK(); - private: HeapProfiler(); ~HeapProfiler(); diff --git a/src/api.cc b/src/api.cc index e083cec2e90..268a3b530f3 100644 --- a/src/api.cc +++ b/src/api.cc @@ -65,7 +65,6 @@ #include "src/v8threads.h" #include "src/version.h" #include "src/vm-state-inl.h" -#include "src/xdk-allocation.h" namespace v8 { @@ -8179,10 +8178,6 @@ int CpuProfileNode::GetColumnNumber() const { entry()->column_number(); } -int CpuProfileNode::GetSrcLine() const { - const i::ProfileNode* node = reinterpret_cast(this); - return node->src_line(); -} unsigned int CpuProfileNode::GetHitLineCount() const { const i::ProfileNode* node = reinterpret_cast(this); @@ -8424,41 +8419,6 @@ void HeapSnapshot::Delete() { } } -const char* HeapEventXDK::getSymbols() { - const i::HeapEventXDK* eventXDK = - reinterpret_cast(this); - return eventXDK->symbols(); -} - -const char* HeapEventXDK::getFrames() { - const i::HeapEventXDK* eventXDK = - reinterpret_cast(this); - return eventXDK->frames(); -} - -const char* HeapEventXDK::getTypes() { - const i::HeapEventXDK* eventXDK = - reinterpret_cast(this); - return eventXDK->types(); -} - -const char* HeapEventXDK::getChunks() { - const i::HeapEventXDK* eventXDK = - reinterpret_cast(this); - return eventXDK->chunks(); -} - -const char* HeapEventXDK::getRetentions() { - const i::HeapEventXDK* eventXDK = - reinterpret_cast(this); - return eventXDK->retentions(); -} - -unsigned int HeapEventXDK::getDuration() { - const i::HeapEventXDK* eventXDK = - reinterpret_cast(this); - return eventXDK->duration(); -} const HeapGraphNode* HeapSnapshot::GetRoot() const { return reinterpret_cast(ToInternal(this)->root()); @@ -8577,20 +8537,6 @@ AllocationProfile* HeapProfiler::GetAllocationProfile() { return reinterpret_cast(this)->GetAllocationProfile(); } -void HeapProfiler::GetHeapXDKStats(OutputStream* stream) { - reinterpret_cast(this)->PushHeapObjectsXDKStats(stream); -} - -void HeapProfiler::StartTrackingHeapObjectsXDK(int stackDepth, bool retentions, - bool strict_collection) { - reinterpret_cast(this)->StartHeapObjectsTrackingXDK( - stackDepth, retentions, strict_collection); -} - -HeapEventXDK* HeapProfiler::StopTrackingHeapObjectsXDK() { - return reinterpret_cast( - reinterpret_cast(this)->StopHeapObjectsTrackingXDK()); -} void HeapProfiler::DeleteAllHeapSnapshots() { reinterpret_cast(this)->DeleteAllSnapshots(); diff --git a/src/profiler/heap-profiler.cc b/src/profiler/heap-profiler.cc index 45109781f1e..1305cae66ea 100644 --- a/src/profiler/heap-profiler.cc +++ b/src/profiler/heap-profiler.cc @@ -9,7 +9,6 @@ #include "src/profiler/allocation-tracker.h" #include "src/profiler/heap-snapshot-generator-inl.h" #include "src/profiler/sampling-heap-profiler.h" -#include "src/xdk-allocation.h" namespace v8 { namespace internal { @@ -68,7 +67,7 @@ HeapSnapshot* HeapProfiler::TakeSnapshot( v8::HeapProfiler::ObjectNameResolver* resolver) { HeapSnapshot* result = new HeapSnapshot(this); { - HeapSnapshotGenerator generator(this, result, control, resolver, heap()); + HeapSnapshotGenerator generator(result, control, resolver, heap()); if (!generator.GenerateSnapshot()) { delete result; result = NULL; @@ -138,42 +137,6 @@ void HeapProfiler::StopHeapObjectsTracking() { } } -void HeapProfiler::StartHeapObjectsTrackingXDK(int stackDepth, bool retentions, - bool strict_collection) { - ids_->UpdateHeapObjectsMap(); - is_tracking_object_moves_ = true; - DCHECK(!is_tracking_allocations()); - allocation_tracker_xdk_.Reset( - new XDKAllocationTracker(this, ids_.get(), names_.get(), stackDepth, - retentions, strict_collection)); - heap()->DisableInlineAllocation(); - // init pre collected objects - allocation_tracker_xdk_->CollectFreedObjects(false, true); -} - -void HeapProfiler::PushHeapObjectsXDKStats(OutputStream* stream) { - // get the garbage here - if (!allocation_tracker_xdk_.is_empty()) { - allocation_tracker_xdk_->CollectFreedObjects(); - OutputStream::WriteResult result = - allocation_tracker_xdk_->SendChunk(stream); - // TODO(amalyshe): it's interesting why CDT can return kAbort. Need to - // investigate if we need add better error generation in the - // allocation_tracker_xdk_->SendChunk - if (result == OutputStream::kAbort) return; - stream->EndOfStream(); - } -} - -v8::internal::HeapEventXDK* HeapProfiler::StopHeapObjectsTrackingXDK() { - HeapEventXDK* event = NULL; - if (!allocation_tracker_xdk_.is_empty()) { - event = allocation_tracker_xdk_->stopTracking(); - allocation_tracker_xdk_.Reset(NULL); - heap()->EnableInlineAllocation(); - } - return event; -} size_t HeapProfiler::GetMemorySizeUsedByProfiler() { size_t size = sizeof(*this); @@ -206,13 +169,9 @@ SnapshotObjectId HeapProfiler::GetSnapshotObjectId(Handle obj) { void HeapProfiler::ObjectMoveEvent(Address from, Address to, int size) { base::LockGuard guard(&profiler_mutex_); - if (allocation_tracker_xdk_.is_empty()) { - bool known_object = ids_->MoveObject(from, to, size); - if (!known_object && !allocation_tracker_.is_empty()) { - allocation_tracker_->address_to_trace()->MoveObject(from, to, size); - } - } else { - allocation_tracker_xdk_->OnMove(from, to, size); + bool known_object = ids_->MoveObject(from, to, size); + if (!known_object && !allocation_tracker_.is_empty()) { + allocation_tracker_->address_to_trace()->MoveObject(from, to, size); } } @@ -222,9 +181,6 @@ void HeapProfiler::AllocationEvent(Address addr, int size) { if (!allocation_tracker_.is_empty()) { allocation_tracker_->AllocationEvent(addr, size); } - if (!allocation_tracker_xdk_.is_empty()) { - allocation_tracker_xdk_->OnAlloc(addr, size); - } } diff --git a/src/profiler/heap-profiler.h b/src/profiler/heap-profiler.h index dc5e43d7f7b..32e143c74ff 100644 --- a/src/profiler/heap-profiler.h +++ b/src/profiler/heap-profiler.h @@ -17,8 +17,6 @@ class AllocationTracker; class HeapObjectsMap; class HeapSnapshot; class SamplingHeapProfiler; -class HeapEventXDK; -class XDKAllocationTracker; class StringsStorage; class HeapProfiler { @@ -47,11 +45,6 @@ class HeapProfiler { SnapshotObjectId PushHeapObjectsStats(OutputStream* stream, int64_t* timestamp_us); - void PushHeapObjectsXDKStats(OutputStream* stream); - void StartHeapObjectsTrackingXDK(int stackDepth, bool retentions, - bool strict_collection = false); - v8::internal::HeapEventXDK* StopHeapObjectsTrackingXDK(); - int GetSnapshotsCount(); HeapSnapshot* GetSnapshot(int index); SnapshotObjectId GetSnapshotObjectId(Handle obj); @@ -73,8 +66,7 @@ class HeapProfiler { bool is_tracking_object_moves() const { return is_tracking_object_moves_; } bool is_tracking_allocations() const { - return (!allocation_tracker_.is_empty() || - !allocation_tracker_xdk_.is_empty()); + return !allocation_tracker_.is_empty(); } Handle FindHeapObjectById(SnapshotObjectId id); @@ -91,7 +83,6 @@ class HeapProfiler { base::SmartPointer names_; List wrapper_callbacks_; base::SmartPointer allocation_tracker_; - base::SmartPointer allocation_tracker_xdk_; bool is_tracking_object_moves_; base::Mutex profiler_mutex_; base::SmartPointer sampling_heap_profiler_; diff --git a/src/profiler/heap-snapshot-generator-inl.h b/src/profiler/heap-snapshot-generator-inl.h index db047957557..169ab569e82 100644 --- a/src/profiler/heap-snapshot-generator-inl.h +++ b/src/profiler/heap-snapshot-generator-inl.h @@ -27,7 +27,7 @@ HeapSnapshot* HeapGraphEdge::snapshot() const { int HeapEntry::index() const { - return static_cast(this - &entries_->first()); + return static_cast(this - &snapshot_->entries().first()); } diff --git a/src/profiler/heap-snapshot-generator.cc b/src/profiler/heap-snapshot-generator.cc index 50611d09c5d..77029fe9c01 100644 --- a/src/profiler/heap-snapshot-generator.cc +++ b/src/profiler/heap-snapshot-generator.cc @@ -43,15 +43,14 @@ void HeapGraphEdge::ReplaceToIndexWithEntry(HeapSnapshot* snapshot) { const int HeapEntry::kNoEntry = -1; -HeapEntry::HeapEntry(HeapSnapshot* snapshot, const List* entries, - Type type, const char* name, SnapshotObjectId id, - size_t self_size, unsigned trace_node_id) +HeapEntry::HeapEntry(HeapSnapshot* snapshot, Type type, const char* name, + SnapshotObjectId id, size_t self_size, + unsigned trace_node_id) : type_(type), children_count_(0), children_index_(-1), self_size_(self_size), snapshot_(snapshot), - entries_(entries), name_(name), id_(id), trace_node_id_(trace_node_id) {} @@ -164,16 +163,12 @@ template struct SnapshotSizeConstants; template <> struct SnapshotSizeConstants<4> { static const int kExpectedHeapGraphEdgeSize = 12; - // This variable reflects the size of the HeapEntry structure - // it is increased to the 4 bytes in case of 32bit arch and for - // 8 bytes for 64 bit arch because for isolating HeapEntry from - // snapshot we need to add one more pointer to the List* entries_ - static const int kExpectedHeapEntrySize = 32; + static const int kExpectedHeapEntrySize = 28; }; template <> struct SnapshotSizeConstants<8> { static const int kExpectedHeapGraphEdgeSize = 24; - static const int kExpectedHeapEntrySize = 48; + static const int kExpectedHeapEntrySize = 40; }; } // namespace @@ -264,7 +259,7 @@ HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type, SnapshotObjectId id, size_t size, unsigned trace_node_id) { - HeapEntry entry(this, &this->entries(), type, name, id, size, trace_node_id); + HeapEntry entry(this, type, name, id, size, trace_node_id); entries_.Add(entry); return &entries_.last(); } @@ -777,13 +772,13 @@ void HeapObjectsSet::SetTag(Object* obj, const char* tag) { cache_entry->value = const_cast(tag); } -V8HeapExplorer::V8HeapExplorer(HeapProfiler* profiler, HeapSnapshot* snapshot, +V8HeapExplorer::V8HeapExplorer(HeapSnapshot* snapshot, SnapshottingProgressReportingInterface* progress, v8::HeapProfiler::ObjectNameResolver* resolver) - : heap_(profiler->heap_object_map()->heap()), + : heap_(snapshot->profiler()->heap_object_map()->heap()), snapshot_(snapshot), - names_(profiler->names()), - heap_object_map_(profiler->heap_object_map()), + names_(snapshot_->profiler()->names()), + heap_object_map_(snapshot_->profiler()->heap_object_map()), progress_(progress), filler_(NULL), global_object_name_resolver_(resolver) {} @@ -890,13 +885,12 @@ HeapEntry* V8HeapExplorer::AddEntry(Address address, return snapshot_->AddEntry(type, name, object_id, size, trace_node_id); } -class CDTSnapshotFiller : public SnapshotFiller { +class SnapshotFiller { public: - explicit CDTSnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries) + explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries) : snapshot_(snapshot), names_(snapshot->profiler()->names()), entries_(entries) {} - virtual ~CDTSnapshotFiller() {} HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { HeapEntry* entry = allocator->AllocateEntry(ptr); entries_->Pair(ptr, entry->index()); @@ -1802,15 +1796,11 @@ bool V8HeapExplorer::IterateAndExtractReferences( // Make sure builtin code objects get their builtin tags // first. Otherwise a particular JSFunction object could set // its custom name to a generic builtin. - // TODO(amalyshe): this condition should be refactored for catching - // root extractor - if (snapshot_) { - RootsReferencesExtractor extractor(heap_); - heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG); - extractor.SetCollectingAllReferences(); - heap_->IterateRoots(&extractor, VISIT_ALL); - extractor.FillReferences(this); - } + RootsReferencesExtractor extractor(heap_); + heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG); + extractor.SetCollectingAllReferences(); + heap_->IterateRoots(&extractor, VISIT_ALL); + extractor.FillReferences(this); // We have to do two passes as sometimes FixedArrays are used // to weakly hold their items, and it's impossible to distinguish @@ -2064,11 +2054,9 @@ void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj, void V8HeapExplorer::SetRootGcRootsReference() { - if (snapshot_) { - filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement, - snapshot_->root()->index(), - snapshot_->gc_roots()); - } + filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement, + snapshot_->root()->index(), + snapshot_->gc_roots()); } @@ -2083,11 +2071,9 @@ void V8HeapExplorer::SetUserGlobalReference(Object* child_obj) { void V8HeapExplorer::SetGcRootsReference(VisitorSynchronization::SyncTag tag) { - if (snapshot_) { - filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement, - snapshot_->gc_roots()->index(), - snapshot_->gc_subroot(tag)); - } + filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement, + snapshot_->gc_roots()->index(), + snapshot_->gc_subroot(tag)); } @@ -2243,11 +2229,11 @@ class GlobalHandlesExtractor : public ObjectVisitor { class BasicHeapEntriesAllocator : public HeapEntriesAllocator { public: - BasicHeapEntriesAllocator(HeapProfiler* profiler, HeapSnapshot* snapshot, + BasicHeapEntriesAllocator(HeapSnapshot* snapshot, HeapEntry::Type entries_type) : snapshot_(snapshot), - names_(profiler->names()), - heap_object_map_(profiler->heap_object_map()), + names_(snapshot_->profiler()->names()), + heap_object_map_(snapshot_->profiler()->heap_object_map()), entries_type_(entries_type) {} virtual HeapEntry* AllocateEntry(HeapThing ptr); private: @@ -2275,19 +2261,18 @@ HeapEntry* BasicHeapEntriesAllocator::AllocateEntry(HeapThing ptr) { } NativeObjectsExplorer::NativeObjectsExplorer( - HeapProfiler* profiler, HeapSnapshot* snapshot, - SnapshottingProgressReportingInterface* progress) - : isolate_(profiler->heap_object_map()->heap()->isolate()), + HeapSnapshot* snapshot, SnapshottingProgressReportingInterface* progress) + : isolate_(snapshot->profiler()->heap_object_map()->heap()->isolate()), snapshot_(snapshot), - names_(profiler->names()), + names_(snapshot_->profiler()->names()), embedder_queried_(false), objects_by_info_(RetainedInfosMatch), native_groups_(StringsMatch), filler_(NULL) { synthetic_entries_allocator_ = - new BasicHeapEntriesAllocator(profiler, snapshot, HeapEntry::kSynthetic); + new BasicHeapEntriesAllocator(snapshot, HeapEntry::kSynthetic); native_entries_allocator_ = - new BasicHeapEntriesAllocator(profiler, snapshot, HeapEntry::kNative); + new BasicHeapEntriesAllocator(snapshot, HeapEntry::kNative); } @@ -2516,16 +2501,13 @@ void NativeObjectsExplorer::VisitSubtreeWrapper(Object** p, uint16_t class_id) { } HeapSnapshotGenerator::HeapSnapshotGenerator( - HeapProfiler* profiler, HeapSnapshot* snapshot, - v8::ActivityControl* control, - v8::HeapProfiler::ObjectNameResolver* resolver, Heap* heap, - SnapshotFiller* filler) + HeapSnapshot* snapshot, v8::ActivityControl* control, + v8::HeapProfiler::ObjectNameResolver* resolver, Heap* heap) : snapshot_(snapshot), control_(control), - v8_heap_explorer_(profiler, snapshot_, this, resolver), - dom_explorer_(profiler, snapshot_, this), - heap_(heap), - filler_(filler) {} + v8_heap_explorer_(snapshot_, this, resolver), + dom_explorer_(snapshot_, this), + heap_(heap) {} bool HeapSnapshotGenerator::GenerateSnapshot() { v8_heap_explorer_.TagGlobalObjects(); @@ -2556,16 +2538,12 @@ bool HeapSnapshotGenerator::GenerateSnapshot() { } #endif - if (snapshot_) { - snapshot_->AddSyntheticRootEntries(); - } + snapshot_->AddSyntheticRootEntries(); if (!FillReferences()) return false; - if (snapshot_) { - snapshot_->FillChildren(); - snapshot_->RememberLastJSObjectId(); - } + snapshot_->FillChildren(); + snapshot_->RememberLastJSObjectId(); progress_counter_ = progress_total_; if (!ProgressReport(true)) return false; @@ -2601,16 +2579,9 @@ void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) { bool HeapSnapshotGenerator::FillReferences() { - if (!filler_) { - CDTSnapshotFiller filler(snapshot_, &entries_); - return v8_heap_explorer_.IterateAndExtractReferences(&filler) && - dom_explorer_.IterateAndExtractReferences(&filler); - } else { - // TODO(amalyshe): finally this need to be returned back when XDK heap - // profiler supports toot extractor - // v8_heap_explorer_.AddRootEntries(filler_); - return v8_heap_explorer_.IterateAndExtractReferences(filler_); - } + SnapshotFiller filler(snapshot_, &entries_); + return v8_heap_explorer_.IterateAndExtractReferences(&filler) && + dom_explorer_.IterateAndExtractReferences(&filler); } diff --git a/src/profiler/heap-snapshot-generator.h b/src/profiler/heap-snapshot-generator.h index d440952ff3f..025d6d93908 100644 --- a/src/profiler/heap-snapshot-generator.h +++ b/src/profiler/heap-snapshot-generator.h @@ -14,7 +14,6 @@ namespace v8 { namespace internal { class AllocationTracker; -class XDKAllocationTracker; class AllocationTraceNode; class HeapEntry; class HeapIterator; @@ -96,9 +95,8 @@ class HeapEntry BASE_EMBEDDED { static const int kNoEntry; HeapEntry() { } - HeapEntry(HeapSnapshot* snapshot, const List* entries, Type type, - const char* name, SnapshotObjectId id, size_t self_size, - unsigned trace_node_id); + HeapEntry(HeapSnapshot* snapshot, Type type, const char* name, + SnapshotObjectId id, size_t self_size, unsigned trace_node_id); HeapSnapshot* snapshot() { return snapshot_; } Type type() { return static_cast(type_); } @@ -134,7 +132,6 @@ class HeapEntry BASE_EMBEDDED { int children_index_; size_t self_size_; HeapSnapshot* snapshot_; - const List* entries_; const char* name_; SnapshotObjectId id_; // id of allocation stack trace top node @@ -328,31 +325,11 @@ class SnapshottingProgressReportingInterface { virtual bool ProgressReport(bool force) = 0; }; -class SnapshotFiller { - public: - virtual ~SnapshotFiller() {} - - virtual HeapEntry* AddEntry(HeapThing ptr, - HeapEntriesAllocator* allocator) = 0; - virtual HeapEntry* FindEntry(HeapThing ptr) = 0; - virtual HeapEntry* FindOrAddEntry(HeapThing ptr, - HeapEntriesAllocator* allocator) = 0; - virtual void SetIndexedReference(HeapGraphEdge::Type type, int parent, - int index, HeapEntry* child_entry) = 0; - virtual void SetIndexedAutoIndexReference(HeapGraphEdge::Type type, - int parent, - HeapEntry* child_entry) = 0; - virtual void SetNamedReference(HeapGraphEdge::Type type, int parent, - const char* reference_name, - HeapEntry* child_entry) = 0; - virtual void SetNamedAutoIndexReference(HeapGraphEdge::Type type, int parent, - HeapEntry* child_entry) = 0; -}; // An implementation of V8 heap graph extractor. class V8HeapExplorer : public HeapEntriesAllocator { public: - V8HeapExplorer(HeapProfiler* profiler, HeapSnapshot* snapshot, + V8HeapExplorer(HeapSnapshot* snapshot, SnapshottingProgressReportingInterface* progress, v8::HeapProfiler::ObjectNameResolver* resolver); virtual ~V8HeapExplorer(); @@ -503,7 +480,7 @@ class NativeGroupRetainedObjectInfo; // An implementation of retained native objects extractor. class NativeObjectsExplorer { public: - NativeObjectsExplorer(HeapProfiler* profiler, HeapSnapshot* snapshot, + NativeObjectsExplorer(HeapSnapshot* snapshot, SnapshottingProgressReportingInterface* progress); virtual ~NativeObjectsExplorer(); int EstimateObjectsCount(); @@ -558,10 +535,9 @@ class NativeObjectsExplorer { class HeapSnapshotGenerator : public SnapshottingProgressReportingInterface { public: - HeapSnapshotGenerator(HeapProfiler* profiler, HeapSnapshot* snapshot, - v8::ActivityControl* control, + HeapSnapshotGenerator(HeapSnapshot* snapshot, v8::ActivityControl* control, v8::HeapProfiler::ObjectNameResolver* resolver, - Heap* heap, SnapshotFiller* filler = NULL); + Heap* heap); bool GenerateSnapshot(); private: @@ -580,7 +556,6 @@ class HeapSnapshotGenerator : public SnapshottingProgressReportingInterface { int progress_counter_; int progress_total_; Heap* heap_; - SnapshotFiller* filler_; DISALLOW_COPY_AND_ASSIGN(HeapSnapshotGenerator); }; diff --git a/src/profiler/profile-generator-inl.h b/src/profiler/profile-generator-inl.h index 1634c3f8267..15f43a3b01e 100644 --- a/src/profiler/profile-generator-inl.h +++ b/src/profiler/profile-generator-inl.h @@ -29,10 +29,9 @@ CodeEntry::CodeEntry(Logger::LogEventsAndTags tag, const char* name, line_info_(line_info), instruction_start_(instruction_start) {} -ProfileNode::ProfileNode(ProfileTree* tree, CodeEntry* entry, int src_line) +ProfileNode::ProfileNode(ProfileTree* tree, CodeEntry* entry) : tree_(tree), entry_(entry), - src_line_(src_line), self_ticks_(0), children_(CodeEntriesMatch), id_(tree->next_node_id()), diff --git a/src/profiler/profile-generator.cc b/src/profiler/profile-generator.cc index a87fd4a3a41..abcd9e5d888 100644 --- a/src/profiler/profile-generator.cc +++ b/src/profiler/profile-generator.cc @@ -166,38 +166,19 @@ void ProfileNode::CollectDeoptInfo(CodeEntry* entry) { ProfileNode* ProfileNode::FindChild(CodeEntry* entry) { - if (entry) { - StackEntry tmp_stackentry(entry, entry->line_number()); - return ProfileNode::FindChild(&tmp_stackentry); - } - return NULL; -} - -ProfileNode* ProfileNode::FindChild(StackEntry* stackentry) { - HashMap::Entry* map_entry = - children_.Lookup(stackentry->entry, - CodeEntryHash(stackentry->entry) ^ stackentry->srcLine); + HashMap::Entry* map_entry = children_.Lookup(entry, CodeEntryHash(entry)); return map_entry != NULL ? reinterpret_cast(map_entry->value) : NULL; } ProfileNode* ProfileNode::FindOrAddChild(CodeEntry* entry) { - if (entry) { - StackEntry tmp_stackentry(entry, entry->line_number()); - return ProfileNode::FindOrAddChild(&tmp_stackentry); - } - return NULL; -} - -ProfileNode* ProfileNode::FindOrAddChild(StackEntry* stackentry) { - HashMap::Entry* map_entry = children_.LookupOrInsert( - stackentry->entry, - CodeEntryHash(stackentry->entry) ^ stackentry->srcLine); + HashMap::Entry* map_entry = + children_.LookupOrInsert(entry, CodeEntryHash(entry)); ProfileNode* node = reinterpret_cast(map_entry->value); if (node == NULL) { // New node added. - node = new ProfileNode(tree_, stackentry->entry, stackentry->srcLine); + node = new ProfileNode(tree_, entry); map_entry->value = node; children_list_.Add(node); } @@ -310,27 +291,13 @@ unsigned ProfileTree::GetFunctionId(const ProfileNode* node) { } ProfileNode* ProfileTree::AddPathFromEnd(const std::vector& path, - int src_line) { - if (path.empty()) return root_; - std::vector stackentrys(path.size()); - auto c = stackentrys.begin(); - for (auto e = path.begin(); e != path.end(); e++, c++) { - if (*e == NULL) continue; - c->entry = *e; - c->srcLine = (*e)->line_number(); - } - return ProfileTree::AddPathFromEnd(stackentrys, src_line); -} - -ProfileNode* ProfileTree::AddPathFromEnd(const std::vector& path, int src_line, bool update_stats) { ProfileNode* node = root_; CodeEntry* last_entry = NULL; - for (auto stackentry = path.rbegin(); - stackentry != path.rend(); ++stackentry) { - if (stackentry->entry == NULL) continue; - node = node->FindOrAddChild(const_cast(&(*stackentry))); - last_entry = node->entry(); + for (auto it = path.rbegin(); it != path.rend(); ++it) { + if (*it == NULL) continue; + last_entry = *it; + node = node->FindOrAddChild(*it); } if (last_entry && last_entry->has_deopt_info()) { node->CollectDeoptInfo(last_entry); @@ -402,7 +369,7 @@ CpuProfile::CpuProfile(Isolate* isolate, const char* title, bool record_samples) top_down_(isolate) {} void CpuProfile::AddPath(base::TimeTicks timestamp, - const std::vector& path, int src_line, + const std::vector& path, int src_line, bool update_stats) { ProfileNode* top_frame_node = top_down_.AddPathFromEnd(path, src_line, update_stats); @@ -571,8 +538,8 @@ void CpuProfilesCollection::RemoveProfile(CpuProfile* profile) { } void CpuProfilesCollection::AddPathToCurrentProfiles( - base::TimeTicks timestamp, const std::vector& path, int src_line, - bool update_stats) { + base::TimeTicks timestamp, const std::vector& path, + int src_line, bool update_stats) { // As starting / stopping profiles is rare relatively to this // method, we don't bother minimizing the duration of lock holding, // e.g. copying contents of the list to a local vector. @@ -622,11 +589,10 @@ ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles) void ProfileGenerator::RecordTickSample(const TickSample& sample) { - std::vector stackentrys; + std::vector entries; // Conservatively reserve space for stack frames + pc + function + vm-state. // There could in fact be more of them because of inlined entries. - stackentrys.reserve(sample.frames_count + 3); - auto stackentry = stackentrys.begin(); + entries.reserve(sample.frames_count + 3); // The ProfileNode knows nothing about all versions of generated code for // the same JS function. The line number information associated with @@ -642,8 +608,7 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) { // Don't use PC when in external callback code, as it can point // inside callback's code, and we will erroneously report // that a callback calls itself. - stackentry->entry = code_map_.FindEntry(sample.external_callback_entry); - stackentry++; + entries.push_back(code_map_.FindEntry(sample.external_callback_entry)); } else { CodeEntry* pc_entry = code_map_.FindEntry(sample.pc); // If there is no pc_entry we're likely in native code. @@ -661,14 +626,12 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) { if (pc_entry) { int pc_offset = static_cast(sample.pc - pc_entry->instruction_start()); - stackentry->entry = pc_entry; - stackentry->srcLine = pc_entry->GetSourceLine(pc_offset); - if (stackentry->srcLine == v8::CpuProfileNode::kNoLineNumberInfo) { - stackentry->srcLine = pc_entry->line_number(); + src_line = pc_entry->GetSourceLine(pc_offset); + if (src_line == v8::CpuProfileNode::kNoLineNumberInfo) { + src_line = pc_entry->line_number(); } - src_line = stackentry->srcLine; src_line_not_found = false; - stackentry++; + entries.push_back(pc_entry); if (pc_entry->builtin_id() == Builtins::kFunctionPrototypeApply || pc_entry->builtin_id() == Builtins::kFunctionPrototypeCall) { @@ -679,8 +642,7 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) { // former case we don't so we simply replace the frame with // 'unresolved' entry. if (sample.top_frame_type == StackFrame::JAVA_SCRIPT) { - stackentry->entry = unresolved_entry_; - stackentry++; + entries.push_back(unresolved_entry_); } } } @@ -689,44 +651,47 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) { for (const Address *stack_pos = sample.stack, *stack_end = stack_pos + sample.frames_count; stack_pos != stack_end; ++stack_pos) { - stackentry->entry = code_map_.FindEntry(*stack_pos); - - // Skip unresolved frames (e.g. internal frame) and get source lines for - // each entry. Save source line (src_line) of the first JS caller - if (stackentry->entry) { - int pc_offset = static_cast( - *stack_pos - stackentry->entry->instruction_start()); - stackentry->srcLine = stackentry->entry->GetSourceLine(pc_offset); - if (stackentry->srcLine == v8::CpuProfileNode::kNoLineNumberInfo) { - stackentry->srcLine = stackentry->entry->line_number(); - } + CodeEntry* entry = code_map_.FindEntry(*stack_pos); + if (entry) { + // Find out if the entry has an inlining stack associated. + int pc_offset = + static_cast(*stack_pos - entry->instruction_start()); + const std::vector* inline_stack = + entry->GetInlineStack(pc_offset); + if (inline_stack) { + entries.insert(entries.end(), inline_stack->rbegin(), + inline_stack->rend()); + } + // Skip unresolved frames (e.g. internal frame) and get source line of + // the first JS caller. if (src_line_not_found) { - src_line = stackentry->srcLine; + src_line = entry->GetSourceLine(pc_offset); + if (src_line == v8::CpuProfileNode::kNoLineNumberInfo) { + src_line = entry->line_number(); + } src_line_not_found = false; } } - - stackentry++; + entries.push_back(entry); } } if (FLAG_prof_browser_mode) { bool no_symbolized_entries = true; - for (auto e = stackentrys.begin(); e != stackentry; ++e) { - if ((*e).entry != NULL) { + for (auto e : entries) { + if (e != NULL) { no_symbolized_entries = false; break; } } // If no frames were symbolized, put the VM state entry in. if (no_symbolized_entries) { - stackentry->entry = EntryForVMState(sample.state); - stackentry++; + entries.push_back(EntryForVMState(sample.state)); } } - profiles_->AddPathToCurrentProfiles(sample.timestamp, stackentrys, src_line, + profiles_->AddPathToCurrentProfiles(sample.timestamp, entries, src_line, sample.update_stats); } diff --git a/src/profiler/profile-generator.h b/src/profiler/profile-generator.h index ebf797feae0..194b4909299 100644 --- a/src/profiler/profile-generator.h +++ b/src/profiler/profile-generator.h @@ -136,36 +136,20 @@ class CodeEntry { DISALLOW_COPY_AND_ASSIGN(CodeEntry); }; -struct StackEntry { - public: - explicit StackEntry(CodeEntry* e = NULL, - int line = v8::CpuProfileNode::kNoLineNumberInfo) - : entry(e), srcLine(line) {} - - CodeEntry* entry; - int srcLine; -}; class ProfileTree; class ProfileNode { public: - inline ProfileNode(ProfileTree* tree, CodeEntry* entry, - int src_line = v8::CpuProfileNode::kNoLineNumberInfo); + inline ProfileNode(ProfileTree* tree, CodeEntry* entry); - ProfileNode* FindChild(StackEntry* stackentry); - ProfileNode* FindOrAddChild(StackEntry* stackentry); - - // Supporting old functions ProfileNode* FindChild(CodeEntry* entry); ProfileNode* FindOrAddChild(CodeEntry* entry); - void IncrementSelfTicks() { ++self_ticks_; } void IncreaseSelfTicks(unsigned amount) { self_ticks_ += amount; } void IncrementLineTicks(int src_line); CodeEntry* entry() const { return entry_; } - int src_line() const { return src_line_; } unsigned self_ticks() const { return self_ticks_; } const List* children() const { return &children_list_; } unsigned id() const { return id_; } @@ -193,7 +177,6 @@ class ProfileNode { ProfileTree* tree_; CodeEntry* entry_; - int src_line_; unsigned self_ticks_; // Mapping from CodeEntry* to ProfileNode* HashMap children_; @@ -213,15 +196,9 @@ class ProfileTree { ~ProfileTree(); ProfileNode* AddPathFromEnd( - const std::vector& path, + const std::vector& path, int src_line = v8::CpuProfileNode::kNoLineNumberInfo, bool update_stats = true); - - // Support old function - ProfileNode* AddPathFromEnd( - const std::vector& path, - int src_line = v8::CpuProfileNode::kNoLineNumberInfo); - ProfileNode* root() const { return root_; } unsigned next_node_id() { return next_node_id_++; } unsigned GetFunctionId(const ProfileNode* node); @@ -253,7 +230,7 @@ class CpuProfile { CpuProfile(Isolate* isolate, const char* title, bool record_samples); // Add pc -> ... -> main() call path to the profile. - void AddPath(base::TimeTicks timestamp, const std::vector& path, + void AddPath(base::TimeTicks timestamp, const std::vector& path, int src_line, bool update_stats); void CalculateTotalTicksAndSamplingRate(); @@ -362,8 +339,9 @@ class CpuProfilesCollection { // Called from profile generator thread. void AddPathToCurrentProfiles(base::TimeTicks timestamp, - const std::vector& path, int src_line, - bool update_stats); + const std::vector& path, + int src_line, bool update_stats); + // Limits the number of profiles that can be simultaneously collected. static const int kMaxSimultaneousProfiles = 100; diff --git a/src/xdk-allocation.cc b/src/xdk-allocation.cc deleted file mode 100644 index e121d61a767..00000000000 --- a/src/xdk-allocation.cc +++ /dev/null @@ -1,526 +0,0 @@ -// Copyright 2014 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include -#include - -#include "src/v8.h" - -#include "src/xdk-allocation.h" - -#include "src/frames-inl.h" -#include "src/xdk-utils.h" - -#include "src/profiler/heap-snapshot-generator-inl.h" - -namespace v8 { -namespace internal { - -static List* g_la_list = NULL; -void XDKGCPrologueCallback(v8::Isolate*, GCType, GCCallbackFlags) { - if (g_la_list) { - g_la_list->Clear(); - } -} - -XDKAllocationTracker::XDKAllocationTracker( - HeapProfiler* heap_profiler, HeapObjectsMap* ids, StringsStorage* names, - int stackDepth, bool collectRetention, bool strict_collection) - : heap_profiler_(heap_profiler), - ids_(ids), - names_(names), - stackDepth_(stackDepth), - collectRetention_(collectRetention), - strict_collection_(strict_collection), - a_treshold_(50), - a_current_(0) { - references_ = new References(); - aggregated_chunks_ = new AggregatedChunks(); - runtime_info_ = new RuntimeInfo(aggregated_chunks_); - symbols_ = new SymbolsStorage(ids_->heap(), names_); - collectedStacks_ = new ShadowStack(); - classNames_ = new ClassNames(names_, ids_->heap()); - - List stack_ooc; - stack_ooc.Add(symbols_->registerSymInfo(1, "OutOfContext", "NoSource", 0, 0)); - outOfContextFrame_ = collectedStacks_->registerStack(stack_ooc); - - List stack_abc; - stack_abc.Add(symbols_->registerSymInfo(2, "AllocatedBeforeCollection", - "NoSource", 0, 0)); - AllocatedBeforeCollectionFrame_ = collectedStacks_->registerStack(stack_abc); - - runtime_info_->InitABCFrame(AllocatedBeforeCollectionFrame_); - - baseTime_ = v8::base::Time::Now(); - latest_delta_ = 0; - - g_la_list = &this->latest_allocations_; - v8::Isolate::GCCallback e = (v8::Isolate::GCCallback)&XDKGCPrologueCallback; - ids_->heap()->AddGCPrologueCallback(e, kGCTypeAll, false); -} - -XDKAllocationTracker::~XDKAllocationTracker() { - delete collectedStacks_; - delete classNames_; - delete aggregated_chunks_; - delete runtime_info_; - delete symbols_; - delete references_; - g_la_list = NULL; -} - -// Heap profiler regularly takes time for storing when object was allocated, -// deallocated, when object's retention snapshot was taken, etc -unsigned int XDKAllocationTracker::GetTimeDelta() { - v8::base::TimeDelta td = v8::base::Time::Now() - baseTime_; - return static_cast(td.InMilliseconds()); -} - -void XDKAllocationTracker::OnAlloc(Address addr, int size) { - DisallowHeapAllocation no_alloc; - Heap* heap = ids_->heap(); - - // below call saves from the crash during StackTraceFrameIterator creation - // Mark the new block as FreeSpace to make sure the heap is iterable - // while we are capturing stack trace. - heap->CreateFillerObjectAt(addr, size, ClearRecordedSlots::kNo); - - Isolate* isolate = heap->isolate(); - StackTraceFrameIterator it(isolate); - List stack; - - // TODO(amalyshe): checking of isolate->handle_scope_data()->level is quite - // artificial. need to understand when we can have such behaviour - // if level == 0 we will crash in getting of source info - while (isolate->handle_scope_data()->level && !it.done() && - stack.length() < stackDepth_) { - JavaScriptFrame* frame = it.frame(); - if (!frame->function()) break; - SharedFunctionInfo* shared = frame->function()->shared(); - if (!shared) break; - - stack.Add(symbols_->FindOrRegisterFrame(frame)); - it.Advance(); - } - - unsigned sid; - if (!stack.is_empty()) { - sid = collectedStacks_->registerStack(stack); - } else { - sid = outOfContextFrame_; - } - - latest_delta_ = GetTimeDelta(); - - PostCollectedInfo* info = - runtime_info_->AddPostCollectedInfo(addr, latest_delta_); - info->size_ = size; - info->timeStamp_ = latest_delta_; - info->stackId_ = sid; - info->className_ = (unsigned int)-1; - info->dirty_ = false; - - // init the type info for previous allocated object - if (latest_allocations_.length() == a_treshold_) { - // resolve next allocation to process - InfoToResolve& allocation = latest_allocations_.at(a_current_); - InitClassName(allocation.address_, allocation.info_); - a_current_++; - if (a_current_ >= a_treshold_) { - a_current_ = 0; - } - } - - if (latest_allocations_.length() < a_treshold_) { - InfoToResolve allocation; - allocation.address_ = addr; - allocation.info_ = info; - latest_allocations_.Add(allocation); - } else { - unsigned allocation_to_update = - a_current_ ? a_current_ - 1 : a_treshold_ - 1; - InfoToResolve& allocation = latest_allocations_.at(allocation_to_update); - allocation.address_ = addr; - allocation.info_ = info; - } -} - -void XDKAllocationTracker::OnMove(Address from, Address to, int size) { - DisallowHeapAllocation no_alloc; - // look for the prev address - PostCollectedInfo* info_from = runtime_info_->FindPostCollectedInfo(from); - if (info_from == NULL) { - return; - } - - runtime_info_->AddPostCollectedInfo(to, latest_delta_, info_from); - runtime_info_->RemoveInfo(from); -} - -HeapEventXDK* XDKAllocationTracker::stopTracking() { - std::string symbols, types, frames, chunks, retentions; - SerializeChunk(&symbols, &types, &frames, &chunks, &retentions); - CollectFreedObjects(true); - std::string symbolsA, typesA, framesA, chunksA, retentionsA; - SerializeChunk(&symbolsA, &typesA, &framesA, &chunksA, &retentionsA, true); - - // TODO(amalyshe): check who releases this object - new HeapEventXDK - return (new HeapEventXDK(GetTimeDelta(), symbols + symbolsA, types + typesA, - frames + framesA, chunks + chunksA, "")); -} - -void XDKAllocationTracker::CollectFreedObjects(bool bAll, bool initPreCollect) { - clearIndividualReteiners(); - if (collectRetention_) { - XDKSnapshotFiller filler(ids_, names_, this); - HeapSnapshotGenerator generator(heap_profiler_, NULL, NULL, NULL, - ids_->heap(), &filler); - generator.GenerateSnapshot(); - } - - Heap* heap = ids_->heap(); - if (!heap) { - return; - } - - unsigned int ts = GetTimeDelta(); - if (bAll) { - ts += RETAINED_DELTA; - } - - // CDT heap profiler calls CollectAllGarbage twice because after the first - // pass there are weak retained object not collected, but due to perf issues - // and because we do garbage collection regularly, we leave here only one call - // only for strict collection like in test where we need to make sure that - // object is definitely collected, we collect twice - heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, - "XDKAllocationTracker::CollectFreedObjects"); - if (strict_collection_) { - heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, - "XDKAllocationTracker::CollectFreedObjects"); - } - std::map individualReteiners; - - // TODO(amalyshe): check what DisallowHeapAllocation no_alloc means because in - // standalone v8 this part is crashed if DisallowHeapAllocation is defined - // DisallowHeapAllocation no_alloc; - if (!bAll) { - HeapIterator iterator(heap); - HeapObject* obj = iterator.next(); - for (; obj != NULL; obj = iterator.next()) { - Address addr = obj->address(); - - PostCollectedInfo* info = runtime_info_->FindPostCollectedInfo(addr); - if (!info) { - // if we don't find info, we consider it as pre collection allocated - // object. need to add to the full picture for retentions - if (initPreCollect) { - info = runtime_info_->AddPreCollectionInfo(addr, obj->Size()); - } - } - - if (info) { - info->dirty_ = true; - } - // check of the class name and its initialization - if ((info && info->className_ == (unsigned)-1) || !info) { - InitClassName(addr, ts, obj->Size()); - } - } - } - - if (collectRetention_) { - std::map::const_iterator citir = - individualReteiners_.begin(); - while (citir != individualReteiners_.end()) { - PostCollectedInfo* infoChild = - runtime_info_->FindPostCollectedInfo(citir->first); - if (infoChild) { - RefId rfId; - rfId.stackId_ = infoChild->stackId_; - rfId.classId_ = infoChild->className_; - - references_->addReference(rfId, citir->second, infoChild->timeStamp_); - } - citir++; - } - } - - runtime_info_->CollectGarbaged(ts); -} - -void XDKAllocationTracker::SerializeChunk(std::string* symbols, - std::string* types, - std::string* frames, - std::string* chunks, - std::string* retentions, bool final) { - if (final) { - *symbols = symbols_->SerializeChunk(); - *types = classNames_->SerializeChunk(); - } - *frames = collectedStacks_->SerializeChunk(); - *chunks = aggregated_chunks_->SerializeChunk(); - - *retentions = references_->serialize(); - std::stringstream retentionsT; - retentionsT << GetTimeDelta() << std::endl << retentions->c_str(); - *retentions = retentionsT.str(); - references_->clear(); -} - -OutputStream::WriteResult XDKAllocationTracker::SendChunk( - OutputStream* stream) { - // go over all aggregated_ and send data to the stream - std::string symbols, types, frames, chunks, retentions; - SerializeChunk(&symbols, &types, &frames, &chunks, &retentions); - - OutputStream::WriteResult ret = stream->WriteHeapXDKChunk( - symbols.c_str(), symbols.length(), frames.c_str(), frames.length(), - types.c_str(), types.length(), chunks.c_str(), chunks.length(), - retentions.c_str(), retentions.length()); - return ret; -} - -unsigned XDKAllocationTracker::GetTraceNodeId(Address address) { - PostCollectedInfo* info = runtime_info_->FindPostCollectedInfo(address); - if (info) { - return info->stackId_; - } else { - return AllocatedBeforeCollectionFrame_; - } -} - -void XDKAllocationTracker::clearIndividualReteiners() { - individualReteiners_.clear(); -} - -std::map* XDKAllocationTracker::GetIndividualReteiners() { - return &individualReteiners_; -} - -unsigned XDKAllocationTracker::FindClassName(Address address) { - PostCollectedInfo* info = runtime_info_->FindPostCollectedInfo(address); - if (info) { - return info->className_; - } else { - return (unsigned)-1; - } -} - -unsigned XDKAllocationTracker::InitClassName(Address address, - PostCollectedInfo* info) { - if (info->className_ == (unsigned)-1) { - info->className_ = classNames_->GetConstructorName(address, runtime_info_); - } - return info->className_; -} - -unsigned XDKAllocationTracker::InitClassName(Address address, unsigned ts, - unsigned size) { - PostCollectedInfo* info = runtime_info_->FindPostCollectedInfo(address); - if (!info) { - info = runtime_info_->AddPostCollectedInfo(address, ts); - info->className_ = -1; - info->stackId_ = outOfContextFrame_; - info->timeStamp_ = ts; - info->size_ = size; - } - return InitClassName(address, info); -} - -unsigned XDKAllocationTracker::FindOrInitClassName(Address address, - unsigned ts) { - unsigned id = FindClassName(address); - if (id == (unsigned)-1) { - // TODO(amalyshe) check if 0 size here is appropriate - id = InitClassName(address, ts, 0); - } - return id; -} - -// ----------------------------------------------------------------------------- -// this is almost a copy and duplication of -// V8HeapExplorer::AddEntry. refactoring is impossible because -// heap-snapshot-generator rely on it's structure which is not fully suitable -// for us. -HeapEntry* XDKSnapshotFiller::AddEntry(HeapThing ptr, - HeapEntriesAllocator* allocator) { - HeapObject* object = reinterpret_cast(ptr); - if (object->IsJSFunction()) { - JSFunction* func = JSFunction::cast(object); - SharedFunctionInfo* shared = func->shared(); - const char* name = names_->GetName(String::cast(shared->name())); - return AddEntry(ptr, object, HeapEntry::kClosure, name); - } else if (object->IsJSBoundFunction()) { - return AddEntry(ptr, object, HeapEntry::kClosure, "native_bind"); - } else if (object->IsJSRegExp()) { - JSRegExp* re = JSRegExp::cast(object); - return AddEntry(ptr, object, HeapEntry::kRegExp, - names_->GetName(re->Pattern())); - } else if (object->IsJSObject()) { - return AddEntry(ptr, object, HeapEntry::kObject, ""); - } else if (object->IsString()) { - String* string = String::cast(object); - if (string->IsConsString()) - return AddEntry(ptr, object, HeapEntry::kConsString, - "(concatenated string)"); - if (string->IsSlicedString()) - return AddEntry(ptr, object, HeapEntry::kSlicedString, "(sliced string)"); - return AddEntry(ptr, object, HeapEntry::kString, - names_->GetName(String::cast(object))); - } else if (object->IsSymbol()) { - return AddEntry(ptr, object, HeapEntry::kSymbol, "symbol"); - } else if (object->IsCode()) { - return AddEntry(ptr, object, HeapEntry::kCode, ""); - } else if (object->IsSharedFunctionInfo()) { - String* name = String::cast(SharedFunctionInfo::cast(object)->name()); - return AddEntry(ptr, object, HeapEntry::kCode, names_->GetName(name)); - } else if (object->IsScript()) { - Object* name = Script::cast(object)->name(); - return AddEntry( - ptr, object, HeapEntry::kCode, - name->IsString() ? names_->GetName(String::cast(name)) : ""); - } else if (object->IsNativeContext()) { - return AddEntry(ptr, object, HeapEntry::kHidden, "system / NativeContext"); - } else if (object->IsContext()) { - return AddEntry(ptr, object, HeapEntry::kObject, "system / Context"); - } else if (object->IsFixedArray() || object->IsFixedDoubleArray() || - object->IsByteArray()) { - return AddEntry(ptr, object, HeapEntry::kArray, ""); - } else if (object->IsHeapNumber()) { - return AddEntry(ptr, object, HeapEntry::kHeapNumber, "number"); - } - - return AddEntry(ptr, object, HeapEntry::kHidden, "system / NOT SUPORTED YET"); -} - -HeapEntry* XDKSnapshotFiller::AddEntry(HeapThing thing, HeapObject* object, - HeapEntry::Type type, const char* name) { - Address address = object->address(); - unsigned trace_node_id = 0; - trace_node_id = allocation_tracker_->GetTraceNodeId(address); - - // cannot store pointer in the map because List reallcoates content regularly - // and the only one way to find the entry - by index. so, index is cached in - // the map - // TODO(amalyshe): need to reuse type. it seems it is important - HeapEntry entry(NULL, &heap_entries_list_, type, name, 0, 0, trace_node_id); - heap_entries_list_.Add(entry); - HeapEntry* pEntry = &heap_entries_list_.last(); - - HashMap::Entry* cache_entry = - heap_entries_.LookupOrInsert(thing, Hash(thing)); - DCHECK(cache_entry->value == NULL); - int index = pEntry->index(); - cache_entry->value = reinterpret_cast(static_cast(index)); - - // TODO(amalyshe): it seems this storage might be optimized - HashMap::Entry* address_entry = index_to_address_.LookupOrInsert( - reinterpret_cast(index + 1), HashInt(index + 1)); - address_entry->value = reinterpret_cast(address); - - return pEntry; -} - -HeapEntry* XDKSnapshotFiller::FindEntry(HeapThing thing) { - HashMap::Entry* cache_entry = heap_entries_.Lookup(thing, Hash(thing)); - if (cache_entry == NULL) return NULL; - return &heap_entries_list_[static_cast( - reinterpret_cast(cache_entry->value))]; -} - -HeapEntry* XDKSnapshotFiller::FindOrAddEntry(HeapThing ptr, - HeapEntriesAllocator* allocator) { - HeapEntry* entry = FindEntry(ptr); - return entry != NULL ? entry : AddEntry(ptr, allocator); -} - -void XDKSnapshotFiller::SetIndexedReference(HeapGraphEdge::Type type, - int parent, int index, - HeapEntry* child_entry) { - if (child_entry->trace_node_id() < 3) { - return; - } - HashMap::Entry* address_entry_child = index_to_address_.Lookup( - reinterpret_cast(child_entry->index() + 1), - HashInt(child_entry->index() + 1)); - DCHECK(address_entry_child != NULL); - if (!address_entry_child) { - return; - } - - Address child_addr = reinterpret_cast
(address_entry_child->value); - - std::map* individualReteiners = - allocation_tracker_->GetIndividualReteiners(); - // get the parent's address, constructor name and form the RefId - HashMap::Entry* address_entry = index_to_address_.Lookup( - reinterpret_cast(parent + 1), HashInt(parent + 1)); - DCHECK(address_entry != NULL); - if (!address_entry) { - return; - } - HeapEntry* parent_entry = &(heap_entries_list_[parent]); - Address parent_addr = reinterpret_cast
(address_entry->value); - RefId parent_ref_id; - parent_ref_id.stackId_ = parent_entry->trace_node_id(); - parent_ref_id.classId_ = - allocation_tracker_->FindOrInitClassName(parent_addr, 0); - - std::stringstream str; - str << index << " element in Array"; - parent_ref_id.field_ = str.str(); - - (*individualReteiners)[child_addr].references_.insert(parent_ref_id); -} - -void XDKSnapshotFiller::SetIndexedAutoIndexReference(HeapGraphEdge::Type type, - int parent, - HeapEntry* child_entry) {} - -void XDKSnapshotFiller::SetNamedReference(HeapGraphEdge::Type type, int parent, - const char* reference_name, - HeapEntry* child_entry) { - if (child_entry->trace_node_id() < 3) { - return; - } - - std::map* individualReteiners = - allocation_tracker_->GetIndividualReteiners(); - // get the parent's address, constructor name and form the RefId - HashMap::Entry* address_entry = index_to_address_.Lookup( - reinterpret_cast(parent + 1), HashInt(parent + 1)); - DCHECK(address_entry != NULL); - if (!address_entry) { - return; - } - HeapEntry* parent_entry = &(heap_entries_list_[parent]); - Address parent_addr = reinterpret_cast
(address_entry->value); - RefId parent_ref_id; - parent_ref_id.stackId_ = parent_entry->trace_node_id(); - // TODO(amalyshe): need to get access to classNames_ - parent_ref_id.classId_ = - allocation_tracker_->FindOrInitClassName(parent_addr, 0); - parent_ref_id.field_ = reference_name; - - HashMap::Entry* address_entry_child = index_to_address_.Lookup( - reinterpret_cast(child_entry->index() + 1), - HashInt(child_entry->index() + 1)); - DCHECK(address_entry_child != NULL); - if (!address_entry_child) { - return; - } - Address child_addr = reinterpret_cast
(address_entry_child->value); - - (*individualReteiners)[child_addr].references_.insert(parent_ref_id); -} - -void XDKSnapshotFiller::SetNamedAutoIndexReference(HeapGraphEdge::Type type, - int parent, - HeapEntry* child_entry) {} - -} // namespace internal - -} // namespace v8 diff --git a/src/xdk-allocation.h b/src/xdk-allocation.h deleted file mode 100644 index 17e8fdf9c47..00000000000 --- a/src/xdk-allocation.h +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2014 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef V8_XDK_ALLOCATION_H_ -#define V8_XDK_ALLOCATION_H_ - -#include -#include -#include "src/base/platform/time.h" - -#include "src/profiler/heap-snapshot-generator.h" - -namespace v8 { -namespace internal { - -class HeapObjectsMap; -class HeapEventXDK; -class ClassNames; -class ShadowStack; -class SymbolsStorage; -class AggregatedChunks; -class RuntimeInfo; -class References; -struct RefSet; -struct PostCollectedInfo; - -class XDKSnapshotFiller : public SnapshotFiller { - public: - explicit XDKSnapshotFiller(HeapObjectsMap* heap_object_map, - StringsStorage* names, - XDKAllocationTracker* allocation_tracker) - : names_(names), - allocation_tracker_(allocation_tracker), - heap_entries_(HashMap::PointersMatch), - index_to_address_(HashMap::PointersMatch) {} - virtual ~XDKSnapshotFiller() {} - - HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator); - HeapEntry* FindEntry(HeapThing thing); - HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator); - void SetIndexedReference(HeapGraphEdge::Type type, int parent, int index, - HeapEntry* child_entry); - void SetIndexedAutoIndexReference(HeapGraphEdge::Type type, int parent, - HeapEntry* child_entry); - void SetNamedReference(HeapGraphEdge::Type type, int parent, - const char* reference_name, HeapEntry* child_entry); - void SetNamedAutoIndexReference(HeapGraphEdge::Type type, int parent, - HeapEntry* child_entry); - - private: - StringsStorage* names_; - XDKAllocationTracker* allocation_tracker_; - HashMap heap_entries_; - HashMap index_to_address_; - - List heap_entries_list_; - - HeapEntry* AddEntry(HeapThing thing, HeapObject* object, HeapEntry::Type type, - const char* name); - - static uint32_t Hash(HeapThing thing) { - return ComputeIntegerHash( - static_cast(reinterpret_cast(thing)), - v8::internal::kZeroHashSeed); - } - static uint32_t HashInt(int key) { - return ComputeIntegerHash(key, v8::internal::kZeroHashSeed); - } -}; - -struct InfoToResolve { - Address address_; - PostCollectedInfo* info_; -}; - -class XDKAllocationTracker { - public: - XDKAllocationTracker(HeapProfiler* heap_profiler, HeapObjectsMap* ids, - StringsStorage* names, int stackDepth, - bool collectRetention, bool strict_collection); - ~XDKAllocationTracker(); - - void OnAlloc(Address addr, int size); - void OnMove(Address from, Address to, int size); - void CollectFreedObjects(bool bAll = false, bool initPreCollect = false); - HeapEventXDK* stopTracking(); - OutputStream::WriteResult SendChunk(OutputStream* stream); - unsigned GetTraceNodeId(Address address); - void clearIndividualReteiners(); - std::map* GetIndividualReteiners(); - - unsigned FindOrInitClassName(Address address, unsigned ts); - - private: - static const int RETAINED_DELTA = 1000; - - // external object - HeapProfiler* heap_profiler_; - HeapObjectsMap* ids_; - StringsStorage* names_; - - AggregatedChunks* aggregated_chunks_; - RuntimeInfo* runtime_info_; - void SerializeChunk(std::string* symbols, std::string* types, - std::string* frames, std::string* chunks, - std::string* retentions, bool final = false); - - unsigned FindClassName(Address address); - unsigned InitClassName(Address address, unsigned ts, unsigned size); - unsigned InitClassName(Address address, PostCollectedInfo* info); - - SymbolsStorage* symbols_; - ShadowStack* collectedStacks_; - ClassNames* classNames_; - - unsigned outOfContextFrame_; - unsigned AllocatedBeforeCollectionFrame_; - - v8::base::Time baseTime_; - unsigned latest_delta_; - unsigned int GetTimeDelta(); - - int stackDepth_; - bool collectRetention_; - bool strict_collection_; - References* references_; - std::map individualReteiners_; - - // here is a loop container which stores the elements not more than - // a_treshold_ and when the capacity is reduced we start - // 1. resolve the a_current_ object's types - // 2. store new allocated object to the a_current_ position - // increas a_current_ until a_treshold_. At the moment when it reach the - // a_treshold_, a_current_ is assigned to 0 - // It id required because some types are defined as a analysis of another - // object and the allocation sequence might be different. Sometimes dependent - // object is allocated first, sometimes parent object is allocated first. - // We cannot find type of latest element, all dependent objects must be - // created - List latest_allocations_; - int a_treshold_; - int a_current_; -}; - -class HeapEventXDK { - public: - HeapEventXDK(unsigned int duration, const std::string& symbols, - const std::string& types, const std::string& frames, - const std::string& chunks, const std::string& retentions) - : symbols_(symbols), - types_(types), - frames_(frames), - chunks_(chunks), - duration_(duration), - retentions_(retentions) {} - - unsigned int duration() const { return duration_; } - const char* symbols() const { return symbols_.c_str(); } - const char* types() const { return types_.c_str(); } - const char* frames() const { return frames_.c_str(); } - const char* chunks() const { return chunks_.c_str(); } - const char* retentions() const { return retentions_.c_str(); } - - private: - std::string symbols_; - std::string types_; - std::string frames_; - std::string chunks_; - unsigned int duration_; - std::string retentions_; - DISALLOW_COPY_AND_ASSIGN(HeapEventXDK); -}; - -} // namespace internal -} // namespace v8 - -#endif // V8_XDK_ALLOCATION_H_ diff --git a/src/xdk-utils.cc b/src/xdk-utils.cc deleted file mode 100644 index 653274f44d7..00000000000 --- a/src/xdk-utils.cc +++ /dev/null @@ -1,616 +0,0 @@ -// Copyright 2014 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "src/v8.h" - -#include "src/frames-inl.h" -#include "src/profiler/strings-storage.h" -#include "src/xdk-utils.h" - -namespace v8 { -namespace internal { - -static bool AddressesMatch(void* key1, void* key2) { return key1 == key2; } - -static uint32_t CharAddressHash(char* addr) { - return ComputeIntegerHash( - static_cast(reinterpret_cast(addr)), - v8::internal::kZeroHashSeed); -} - -static uint32_t AddressHash(Address addr) { - return ComputeIntegerHash( - static_cast(reinterpret_cast(addr)), - v8::internal::kZeroHashSeed); -} - -ClassNames::ClassNames(StringsStorage* names, Heap* heap) - : counter_(0), char_to_idx_(AddressesMatch), names_(names), heap_(heap) { - id_native_bind_ = registerName(names->GetCopy("native_bind")); - id_conc_string_ = registerName(names->GetCopy("(concatenated string)")); - id_sliced_string_ = registerName(names->GetCopy("(sliced string)")); - id_string_ = registerName(names->GetCopy("String")); - id_symbol_ = registerName(names->GetCopy("(symbol)")); - id_code_ = registerName(names->GetCopy("(compiled code)")); - id_system_ncontext_ = - registerName(names->GetCopy("(system / NativeContext)")); - id_system_context_ = registerName(names->GetCopy("(system / Context)")); - id_array_ = registerName(names->GetCopy("(array)")); - id_number_ = registerName(names->GetCopy("(number)")); - id_system_ = registerName(names->GetCopy("(system)")); - id_shared_fi_ = registerName(names->GetCopy("(shared function info)")); - id_script_ = registerName(names->GetCopy("(script)")); - id_regexp_ = registerName(names->GetCopy("RegExp")); - id_function_bindings_ = registerName(names->GetCopy("(function bindings)")); - id_function_literals_ = registerName(names->GetCopy("(function literals)")); - id_objects_properties_ = registerName(names->GetCopy("(object properties)")); - id_objects_elements_ = registerName(names->GetCopy("(object elements)")); - id_shared_function_info_ = - registerName(names->GetCopy("(shared function info)")); - id_context_ = registerName(names->GetCopy("(context)")); - id_code_relocation_info_ = - registerName(names->GetCopy("(code relocation info)")); - id_code_deopt_data_ = registerName(names->GetCopy("(code deopt data)")); -} - -unsigned ClassNames::registerName(const char* name) { - // since const char is retained outside and cannot be moved, we rely on this - // and just compare the pointers. It should be enough for the strings from the - // only one StringStorage - if (!name) { - return -2; - } - - unsigned counter; - HashMap::Entry* entry = char_to_idx_.LookupOrInsert( - const_cast(name), CharAddressHash(const_cast(name))); - if (entry->value == NULL) { - counter = ++counter_; - entry->value = reinterpret_cast(counter); - } else { - counter = static_cast(reinterpret_cast(entry->value)); - } - return counter; -} - -std::string ClassNames::SerializeChunk() { - std::stringstream serialized; - for (HashMap::Entry* p = char_to_idx_.Start(); p != NULL; - p = char_to_idx_.Next(p)) { - serialized << static_cast(reinterpret_cast(p->value)) - << "," << reinterpret_cast(p->key) << std::endl; - } - - return serialized.str(); -} - -bool ClassNames::IsEssentialObject(Object* object) { - return object->IsHeapObject() && !object->IsOddball() && - object != heap_->empty_byte_array() && - object != heap_->empty_fixed_array() && - object != heap_->empty_descriptor_array() && - object != heap_->fixed_array_map() && object != heap_->cell_map() && - object != heap_->global_property_cell_map() && - object != heap_->shared_function_info_map() && - object != heap_->free_space_map() && - object != heap_->one_pointer_filler_map() && - object != heap_->two_pointer_filler_map(); -} - -void ClassNames::registerNameForDependent(HeapObject* object, - RuntimeInfo* runtime_info, - unsigned id) { - if (object && IsEssentialObject(object)) { - PostCollectedInfo* info = - runtime_info->FindPostCollectedInfo(object->address()); - // TODO(amalyshe) here we are loosing some information because - // *some* of the objects are allocated without notification of explicit - // allocation and no XDKAllocationTracker::OnAlloc will be called for them. - // But these objects exist in the heap and can be achieved if we iterate - // through the heap. We cannot add here them explicitly because if - // XDKAllocationTracker::OnAlloc is called for this address, it will remove - // all useful information about type and even report wrong data because - // during removal these objects will be added to statistic and will be - // counted twice - if (info) { - info->className_ = id; - } - } -} - -unsigned ClassNames::GetConstructorName(Address address, - RuntimeInfo* runtime_info) { - unsigned id = (unsigned)-2; - HeapObject* heap_object = HeapObject::FromAddress(address); - - // support of all type, if some are built-in, we add hard-coded values - if (heap_object->IsJSObject()) { - JSObject* object = JSObject::cast(heap_object); - if (object->IsJSBoundFunction()) { - JSBoundFunction* js_fun = JSBoundFunction::cast(object); - registerNameForDependent(js_fun, runtime_info, id_function_bindings_); - } else if (object->IsJSFunction()) { - Heap* heap = object->GetHeap(); - const char* name = names_->GetName(String::cast(heap->closure_string())); - id = registerName(name); - JSFunction* js_fun = JSFunction::cast(object); - SharedFunctionInfo* shared_info = js_fun->shared(); - registerNameForDependent(js_fun->literals(), runtime_info, - id_function_literals_); - registerNameForDependent(shared_info, runtime_info, - id_shared_function_info_); - registerNameForDependent(js_fun->context(), runtime_info, id_context_); - } else { - DisallowHeapAllocation no_gc; - Isolate* isolate = heap_->isolate(); - HandleScope scope(isolate); - String* str_class_name = - *JSReceiver::GetConstructorName(handle(object, isolate)); - const char* name = names_->GetName(str_class_name); - id = registerName(name); - } - HeapObject* prop = reinterpret_cast(object->properties()); - registerNameForDependent(prop, runtime_info, id_objects_properties_); - HeapObject* elements = reinterpret_cast(object->elements()); - registerNameForDependent(elements, runtime_info, id_objects_elements_); - } else if (heap_object->IsJSRegExp()) { - id = id_regexp_; - } else if (heap_object->IsString()) { - String* string = String::cast(heap_object); - if (string->IsConsString()) - id = id_conc_string_; - else if (string->IsSlicedString()) - id = id_sliced_string_; - else - id = id_string_; - } else if (heap_object->IsSymbol()) { - id = id_symbol_; - } else if (heap_object->IsCode()) { - Code* code = Code::cast(heap_object); - registerNameForDependent(code->relocation_info(), runtime_info, - id_code_relocation_info_); - registerNameForDependent(code->deoptimization_data(), runtime_info, - id_code_deopt_data_); - id = id_code_; - } else if (heap_object->IsSharedFunctionInfo()) { - id = id_shared_fi_; - } else if (heap_object->IsScript()) { - id = id_script_; - } else if (heap_object->IsNativeContext()) { - id = id_system_ncontext_; - } else if (heap_object->IsContext()) { - id = id_system_context_; - } else if (heap_object->IsFixedArray() || heap_object->IsFixedDoubleArray() || - heap_object->IsByteArray()) { - id = id_array_; - } else if (heap_object->IsHeapNumber()) { - id = id_number_; - } else { - id = id_system_; - } - - return id; -} - -// ----------------------------------------------------------------------------- -ShadowStack::ShadowStack() { - last_index_ = 1; - serializedCounter_ = last_index_; - root_.index_ = 0; - root_.parent_ = NULL; - root_.callsite_ = 0; -} - -ShadowStack::~ShadowStack() { - // erasing all objects from the current container - std::map::iterator eit = allNodes_.begin(); - while (eit != allNodes_.end()) { - delete eit->second; - eit++; - } -} - -unsigned ShadowStack::registerStack(const List& shadow_stack_) { - // look for the latest node - CallTree* pNode = &root_; - // go over all entries and add them to the tree if they are not in the map - int i, j; - for (i = shadow_stack_.length() - 1; i != -1; i--) { - std::map::iterator it = - pNode->children_.find(shadow_stack_[i]); - if (it == pNode->children_.end()) break; - pNode = it->second; - } - // verification if we need to add something or not - for (j = i; j != -1; j--) { - CallTree* pNodeTmp = new CallTree; - pNodeTmp->index_ = last_index_++; - pNodeTmp->parent_ = pNode; - pNodeTmp->callsite_ = shadow_stack_[j]; - pNode->children_[shadow_stack_[j]] = pNodeTmp; - allNodes_[pNodeTmp->index_] = pNodeTmp; - pNode = pNodeTmp; - } - return pNode->index_; -} - -std::string ShadowStack::SerializeChunk() { - std::stringstream str; - std::map::iterator it = - allNodes_.find(serializedCounter_); - while (it != allNodes_.end()) { - str << it->first << "," << it->second->callsite_ << "," - << it->second->parent_->index_ << std::endl; - it++; - } - - serializedCounter_ = last_index_; - return str.str(); -} - -// ----------------------------------------------------------------------------- -static bool SymInfoMatch(void* key1, void* key2) { - SymInfoKey* key_c1 = reinterpret_cast(key1); - SymInfoKey* key_c2 = reinterpret_cast(key2); - return *key_c1 == *key_c2; -} - -static uint32_t SymInfoHash(const SymInfoKey& key) { - uint32_t hash = 0; - // take the low 16 bits of function_id_ - hash |= (key.function_id_ & 0xffff); - // take the low 8 bits of line_ and column_ and init highest bits - hash |= ((key.line_ & 0xff) << 16); - hash |= ((key.column_ & 0xff) << 14); - - return hash; -} - -struct SymbolCached { - unsigned int symbol_id_; - uintptr_t function_; -}; - -SymbolsStorage::SymbolsStorage(Heap* heap, StringsStorage* names) - : symbols_(SymInfoMatch), - curSym_(1), - sym_info_hash_(AddressesMatch), - heap_(heap), - names_(names) { - reserved_key_ = new SymInfoKey(); -} - -SymbolsStorage::~SymbolsStorage() { - // go over map and delete all keys and values - for (HashMap::Entry* p = symbols_.Start(); p != NULL; p = symbols_.Next(p)) { - delete reinterpret_cast(p->value); - delete reinterpret_cast(p->key); - } - delete reserved_key_; -} - -unsigned SymbolsStorage::registerSymInfo(size_t functionId, - std::string functionName, - std::string sourceName, unsigned line, - unsigned column) { - if (sourceName.empty()) { - sourceName = "unknown"; - } - - reserved_key_->function_id_ = functionId; - reserved_key_->line_ = line; - reserved_key_->column_ = column; - - HashMap::Entry* entry = - symbols_.LookupOrInsert(reserved_key_, SymInfoHash(*reserved_key_)); - if (entry->value) { - return reinterpret_cast(entry->value)->symId_; - } - - // else initialize by new one - SymInfoValue* value = new SymInfoValue; - value->symId_ = curSym_++; - value->funcName_ = functionName; - value->sourceFile_ = sourceName; - entry->value = value; - - // compensation for registered one - reserved_key_ = new SymInfoKey(); - - return value->symId_; -} - -std::string SymbolsStorage::SerializeChunk() { - std::stringstream serialized; - for (HashMap::Entry* p = symbols_.Start(); p != NULL; p = symbols_.Next(p)) { - SymInfoValue* v = reinterpret_cast(p->value); - SymInfoKey* k = reinterpret_cast(p->key); - serialized << v->symId_ << "," << k->function_id_ << "," << v->funcName_ - << "," << v->sourceFile_ << "," << k->line_ << "," << k->column_ - << std::endl; - } - - return serialized.str(); -} - -unsigned SymbolsStorage::FindOrRegisterFrame(JavaScriptFrame* frame) { - SharedFunctionInfo* shared = frame->function()->shared(); - DCHECK(shared); - Isolate* isolate = heap_->isolate(); - - Address pc = frame->pc(); - unsigned int symbolId = 0; - - // We don't rely on the address only. Since this is JIT based language, - // the address might be occupied by other function - // thus we are verifying if the same function takes this place - // before we take symbol info from the cache - HashMap::Entry* sym_entry = sym_info_hash_.LookupOrInsert( - reinterpret_cast(pc), AddressHash(pc)); - if (sym_entry->value == NULL || - (reinterpret_cast(sym_entry->value)->function_ != - reinterpret_cast(frame->function()))) { - if (sym_entry->value) { - delete reinterpret_cast(sym_entry->value); - } - - const char* s = names_->GetFunctionName(shared->DebugName()); - // trying to get the source name and line# - Code* code = Code::cast(isolate->FindCodeObject(pc)); - if (code) { - int offset = - static_cast(pc - frame->LookupCode()->instruction_start()); - int source_pos = code->SourcePosition(offset); - Object* maybe_script = shared->script(); - if (maybe_script && maybe_script->IsScript()) { - Handle