From 949d079b90dcfa5fa918e1f366a6efb689615d20 Mon Sep 17 00:00:00 2001 From: Eurogiciel-BOT Date: Fri, 5 Dec 2014 09:25:55 +0000 Subject: [PATCH 1/1] Upstream version 11.39.260.0 Upstream commit-id 85e147c604c066ea09d5cde269279293e6297424 Change-Id: I618279d0ff8dcd38ec097ef3e4cffa72185b6537 Signed-off-by: Eurogiciel-BOT --- packaging/crosswalk.spec | 2 +- src/v8/src/deoptimizer.h | 2 +- src/v8/src/xdk-allocation.cc | 1078 +++++++++---------- src/v8/src/xdk-allocation.h | 336 +++--- src/v8/src/xdk-utils.cc | 1082 ++++++++++---------- src/v8/src/xdk-utils.h | 498 ++++----- src/xwalk/DEPS.xwalk | 2 +- src/xwalk/VERSION | 2 +- src/xwalk/application/browser/application.cc | 1 + src/xwalk/application/common/application_data.cc | 2 +- .../application/common/application_file_util.cc | 2 +- .../common/application_manifest_constants.cc | 10 +- .../common/application_manifest_constants.h | 8 +- .../manifest_handlers/tizen_application_handler.cc | 4 +- .../manifest_handlers/tizen_appwidget_handler.cc | 12 +- .../common/manifest_handlers/unittest_util.cc | 4 +- .../common/manifest_handlers/widget_handler.cc | 8 +- .../manifest_handlers/widget_handler_unittest.cc | 23 +- src/xwalk/packaging/crosswalk.spec | 2 +- .../browser/devtools/xwalk_devtools_delegate.cc | 6 + src/xwalk/tizen/browser/media/murphy_mainloop.cc | 10 +- .../tizen/common/media/media_player_messages.h | 2 +- .../renderer/media/renderer_mediaplayer_manager.h | 2 +- 23 files changed, 1562 insertions(+), 1536 deletions(-) diff --git a/packaging/crosswalk.spec b/packaging/crosswalk.spec index ee8b27c..8e9c587 100644 --- a/packaging/crosswalk.spec +++ b/packaging/crosswalk.spec @@ -24,7 +24,7 @@ %define _binary_payload w3.gzdio Name: crosswalk -Version: 11.39.258.0 +Version: 11.39.260.0 Release: 0 Summary: Chromium-based app runtime License: (BSD-3-Clause and LGPL-2.1+) diff --git a/src/v8/src/deoptimizer.h b/src/v8/src/deoptimizer.h index 5baf67a..b042b45 100644 --- a/src/v8/src/deoptimizer.h +++ b/src/v8/src/deoptimizer.h @@ -546,7 +546,7 @@ class FrameDescription { // This convoluted DCHECK is needed to work around a gcc problem that // improperly detects an array bounds overflow in optimized debug builds // when using a plain DCHECK. - if (n >= arraysize(registers_) { + if (n >= arraysize(registers_)) { DCHECK(false); return 0; } diff --git a/src/v8/src/xdk-allocation.cc b/src/v8/src/xdk-allocation.cc index 311a592..3d33f80 100644 --- a/src/v8/src/xdk-allocation.cc +++ b/src/v8/src/xdk-allocation.cc @@ -1,539 +1,539 @@ -// 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 "frames-inl.h" -#include "src/xdk-utils.h" - -namespace v8 { -namespace internal { - -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) { - 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_); - - 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; -} - - -XDKAllocationTracker::~XDKAllocationTracker() { - delete collectedStacks_; - delete classNames_; - delete aggregated_chunks_; - delete runtime_info_; - delete symbols_; - delete references_; -} - - -// 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. - FreeListNode::FromAddress(addr)->set_size(heap, size); - - 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; -} - - -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, unsigned ts, - unsigned size) { - unsigned id = -2; - 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; - } - if (info->className_ == (unsigned)-1) { - String* str = classNames_->GetConstructorName(address); - if (str) { - // get const char*, it's safe because pointer will be retained in the - // name_ until it is destroyed - id = classNames_->registerName(names_->GetName(str)); - } - } - info->className_ = id; - return id; -} - - -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 = shared->bound() ? "native_bind" : - names_->GetName(String::cast(shared->name())); - return AddEntry(ptr, object, HeapEntry::kClosure, name); - } 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() || - object->IsExternalArray()) { - 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_.Lookup(thing, Hash(thing), true); - 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_.Lookup( - reinterpret_cast(index+1), HashInt(index+1), true); - address_entry->value = reinterpret_cast(address); - - return pEntry; -} - - -HeapEntry* XDKSnapshotFiller::FindEntry(HeapThing thing) { - HashMap::Entry* cache_entry = heap_entries_.Lookup(thing, Hash(thing), false); - 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), false); - 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), false); - 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), false); - 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), false); - 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 v8::internal +// 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 "frames-inl.h" +#include "src/xdk-utils.h" + +namespace v8 { +namespace internal { + +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) { + 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_); + + 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; +} + + +XDKAllocationTracker::~XDKAllocationTracker() { + delete collectedStacks_; + delete classNames_; + delete aggregated_chunks_; + delete runtime_info_; + delete symbols_; + delete references_; +} + + +// 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. + FreeListNode::FromAddress(addr)->set_size(heap, size); + + 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; +} + + +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, unsigned ts, + unsigned size) { + unsigned id = -2; + 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; + } + if (info->className_ == (unsigned)-1) { + String* str = classNames_->GetConstructorName(address); + if (str) { + // get const char*, it's safe because pointer will be retained in the + // name_ until it is destroyed + id = classNames_->registerName(names_->GetName(str)); + } + } + info->className_ = id; + return id; +} + + +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 = shared->bound() ? "native_bind" : + names_->GetName(String::cast(shared->name())); + return AddEntry(ptr, object, HeapEntry::kClosure, name); + } 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() || + object->IsExternalArray()) { + 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_.Lookup(thing, Hash(thing), true); + 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_.Lookup( + reinterpret_cast(index+1), HashInt(index+1), true); + address_entry->value = reinterpret_cast(address); + + return pEntry; +} + + +HeapEntry* XDKSnapshotFiller::FindEntry(HeapThing thing) { + HashMap::Entry* cache_entry = heap_entries_.Lookup(thing, Hash(thing), false); + 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), false); + 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), false); + 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), false); + 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), false); + 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 v8::internal diff --git a/src/v8/src/xdk-allocation.h b/src/v8/src/xdk-allocation.h index 79384e9..d5305c5 100644 --- a/src/v8/src/xdk-allocation.h +++ b/src/v8/src/xdk-allocation.h @@ -1,168 +1,168 @@ -// 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" - -namespace v8 { -namespace internal { - -class HeapObjectsMap; -class HeapEventXDK; -class ClassNames; -class ShadowStack; -class SymbolsStorage; -class AggregatedChunks; -class RuntimeInfo; -class References; -class RefSet; - - -class XDKSnapshotFiller: public SnapshotFiller { - public: - explicit XDKSnapshotFiller(HeapObjectsMap* heap_object_map, - StringsStorage* names, - XDKAllocationTracker* allocation_tracker) - : names_(names), - heap_object_map_(heap_object_map), - 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_; - HeapObjectsMap* heap_object_map_; - 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); - } -}; - - -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); - - 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_; -}; - - -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 v8::internal - -#endif // V8_XDK_ALLOCATION_H_ +// 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" + +namespace v8 { +namespace internal { + +class HeapObjectsMap; +class HeapEventXDK; +class ClassNames; +class ShadowStack; +class SymbolsStorage; +class AggregatedChunks; +class RuntimeInfo; +class References; +class RefSet; + + +class XDKSnapshotFiller: public SnapshotFiller { + public: + explicit XDKSnapshotFiller(HeapObjectsMap* heap_object_map, + StringsStorage* names, + XDKAllocationTracker* allocation_tracker) + : names_(names), + heap_object_map_(heap_object_map), + 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_; + HeapObjectsMap* heap_object_map_; + 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); + } +}; + + +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); + + 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_; +}; + + +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 v8::internal + +#endif // V8_XDK_ALLOCATION_H_ diff --git a/src/v8/src/xdk-utils.cc b/src/v8/src/xdk-utils.cc index b17eb95..d05dd6d 100644 --- a/src/v8/src/xdk-utils.cc +++ b/src/v8/src/xdk-utils.cc @@ -1,541 +1,541 @@ -// 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/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) - : counter_(0), - char_to_idx_(AddressesMatch), - names_(names) { -} - - -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 - unsigned counter; - HashMap::Entry* entry = char_to_idx_.Lookup(const_cast(name), - CharAddressHash(const_cast(name)), - true); - 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(); -} - - -String* ClassNames::GetConstructorName(Address address) { - HeapObject *heap_object = HeapObject::FromAddress(address); - bool is_js_object = heap_object->IsJSObject(); - if (!is_js_object) { - // TODO(amalyshe): look for another function for taking the class name - // String* constructor_name = object2->constructor_name(); - return NULL; - } - JSObject* object = JSObject::cast(heap_object); - Heap* heap = object->GetHeap(); - if (object->IsJSFunction()) return heap->closure_string(); - return object->constructor_name(); -} - - -// ----------------------------------------------------------------------------- -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_.Lookup(reserved_key_, - SymInfoHash(*reserved_key_), true); - 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_.Lookup( - reinterpret_cast(pc), AddressHash(pc), true); - 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 source_pos = code->SourcePosition(pc); - Object *maybe_script = shared->script(); - if (maybe_script && maybe_script->IsScript()) { - Handle