Upstream version 11.39.260.0 88/31488/1
authorEurogiciel-BOT <eurogiciel.tizen@gmail.com>
Fri, 5 Dec 2014 09:25:55 +0000 (09:25 +0000)
committerEurogiciel-BOT <eurogiciel.tizen@gmail.com>
Fri, 5 Dec 2014 09:25:55 +0000 (09:25 +0000)
Upstream commit-id 85e147c604c066ea09d5cde269279293e6297424

Change-Id: I618279d0ff8dcd38ec097ef3e4cffa72185b6537
Signed-off-by: Eurogiciel-BOT <eurogiciel.tizen@gmail.com>
23 files changed:
packaging/crosswalk.spec
src/v8/src/deoptimizer.h
src/v8/src/xdk-allocation.cc
src/v8/src/xdk-allocation.h
src/v8/src/xdk-utils.cc
src/v8/src/xdk-utils.h
src/xwalk/DEPS.xwalk
src/xwalk/VERSION
src/xwalk/application/browser/application.cc
src/xwalk/application/common/application_data.cc
src/xwalk/application/common/application_file_util.cc
src/xwalk/application/common/application_manifest_constants.cc
src/xwalk/application/common/application_manifest_constants.h
src/xwalk/application/common/manifest_handlers/tizen_application_handler.cc
src/xwalk/application/common/manifest_handlers/tizen_appwidget_handler.cc
src/xwalk/application/common/manifest_handlers/unittest_util.cc
src/xwalk/application/common/manifest_handlers/widget_handler.cc
src/xwalk/application/common/manifest_handlers/widget_handler_unittest.cc
src/xwalk/packaging/crosswalk.spec
src/xwalk/runtime/browser/devtools/xwalk_devtools_delegate.cc
src/xwalk/tizen/browser/media/murphy_mainloop.cc
src/xwalk/tizen/common/media/media_player_messages.h
src/xwalk/tizen/renderer/media/renderer_mediaplayer_manager.h

index ee8b27c..8e9c587 100644 (file)
@@ -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+)
index 5baf67a..b042b45 100644 (file)
@@ -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;
     }
index 311a592..3d33f80 100644 (file)
-// Copyright 2014 the V8 project authors. All rights reserved.\r
-// Use of this source code is governed by a BSD-style license that can be\r
-// found in the LICENSE file.\r
-\r
-#include <sstream>\r
-#include <string>\r
-\r
-#include "src/v8.h"\r
-\r
-#include "src/xdk-allocation.h"\r
-\r
-#include "frames-inl.h"\r
-#include "src/xdk-utils.h"\r
-\r
-namespace v8 {\r
-namespace internal {\r
-\r
-XDKAllocationTracker::XDKAllocationTracker(HeapProfiler* heap_profiler,\r
-                                           HeapObjectsMap *ids,\r
-                                           StringsStorage *names,\r
-                                           int stackDepth,\r
-                                           bool collectRetention,\r
-                                           bool strict_collection)\r
-    : heap_profiler_(heap_profiler),\r
-    ids_(ids),\r
-    names_(names),\r
-    stackDepth_(stackDepth),\r
-    collectRetention_(collectRetention),\r
-    strict_collection_(strict_collection) {\r
-  references_ = new References();\r
-  aggregated_chunks_ = new AggregatedChunks();\r
-  runtime_info_ = new RuntimeInfo(aggregated_chunks_);\r
-  symbols_ = new SymbolsStorage(ids_->heap(), names_);\r
-  collectedStacks_ = new ShadowStack();\r
-  classNames_ = new ClassNames(names_);\r
-\r
-  List<unsigned> stack_ooc;\r
-  stack_ooc.Add(symbols_->registerSymInfo(1, "OutOfContext", "NoSource",\r
-                                          0, 0));\r
-  outOfContextFrame_ = collectedStacks_->registerStack(stack_ooc);\r
-\r
-  List<unsigned> stack_abc;\r
-  stack_abc.Add(symbols_->registerSymInfo(2, "AllocatedBeforeCollection",\r
-                                          "NoSource", 0, 0));\r
-  AllocatedBeforeCollectionFrame_ = collectedStacks_->registerStack(stack_abc);\r
-\r
-  runtime_info_->InitABCFrame(AllocatedBeforeCollectionFrame_);\r
-\r
-  baseTime_ = v8::base::Time::Now();\r
-  latest_delta_ = 0;\r
-}\r
-\r
-\r
-XDKAllocationTracker::~XDKAllocationTracker() {\r
-  delete collectedStacks_;\r
-  delete classNames_;\r
-  delete aggregated_chunks_;\r
-  delete runtime_info_;\r
-  delete symbols_;\r
-  delete references_;\r
-}\r
-\r
-\r
-// Heap profiler regularly takes time for storing when object was allocated,\r
-// deallocated, when object's retention snapshot was taken, etc\r
-unsigned int XDKAllocationTracker::GetTimeDelta() {\r
-  v8::base::TimeDelta td = v8::base::Time::Now() - baseTime_;\r
-  return static_cast<unsigned int>(td.InMilliseconds());\r
-}\r
-\r
-\r
-void XDKAllocationTracker::OnAlloc(Address addr, int size) {\r
-  DisallowHeapAllocation no_alloc;\r
-  Heap *heap = ids_->heap();\r
-\r
-  // below call saves from the crash during StackTraceFrameIterator creation\r
-  // Mark the new block as FreeSpace to make sure the heap is iterable\r
-  // while we are capturing stack trace.\r
-  FreeListNode::FromAddress(addr)->set_size(heap, size);\r
-\r
-  Isolate *isolate = heap->isolate();\r
-  StackTraceFrameIterator it(isolate);\r
-  List<unsigned> stack;\r
-\r
-  // TODO(amalyshe): checking of isolate->handle_scope_data()->level is quite\r
-  // artificial. need to understand when we can have such behaviour\r
-  // if level == 0 we will crash in getting of source info\r
-  while (isolate->handle_scope_data()->level && !it.done() &&\r
-      stack.length() < stackDepth_) {\r
-    JavaScriptFrame *frame = it.frame();\r
-    if (!frame->function())\r
-      break;\r
-    SharedFunctionInfo *shared = frame->function()->shared();\r
-    if (!shared)\r
-      break;\r
-\r
-    stack.Add(symbols_->FindOrRegisterFrame(frame));\r
-    it.Advance();\r
-  }\r
-\r
-  unsigned sid;\r
-  if (!stack.is_empty()) {\r
-    sid = collectedStacks_->registerStack(stack);\r
-  } else {\r
-    sid = outOfContextFrame_;\r
-  }\r
-\r
-  latest_delta_ = GetTimeDelta();\r
-\r
-  PostCollectedInfo* info = runtime_info_->AddPostCollectedInfo(addr,\r
-                                                                latest_delta_);\r
-  info->size_ = size;\r
-  info->timeStamp_ = latest_delta_;\r
-  info->stackId_ = sid;\r
-  info->className_ = (unsigned int)-1;\r
-  info->dirty_ = false;\r
-}\r
-\r
-\r
-void XDKAllocationTracker::OnMove(Address from, Address to, int size) {\r
-  DisallowHeapAllocation no_alloc;\r
-  // look for the prev address\r
-  PostCollectedInfo* info_from = runtime_info_->FindPostCollectedInfo(from);\r
-  if (info_from == NULL) {\r
-    return;\r
-  }\r
-\r
-  runtime_info_->AddPostCollectedInfo(to, latest_delta_, info_from);\r
-  runtime_info_->RemoveInfo(from);\r
-}\r
-\r
-\r
-HeapEventXDK* XDKAllocationTracker::stopTracking() {\r
-  std::string symbols, types, frames, chunks, retentions;\r
-  SerializeChunk(&symbols, &types, &frames, &chunks, &retentions);\r
-  CollectFreedObjects(true);\r
-  std::string symbolsA, typesA, framesA, chunksA, retentionsA;\r
-  SerializeChunk(&symbolsA, &typesA, &framesA, &chunksA, &retentionsA, true);\r
-\r
-  // TODO(amalyshe): check who releases this object - new HeapEventXDK\r
-  return (new HeapEventXDK(GetTimeDelta(), symbols+symbolsA, types+typesA,\r
-      frames+framesA, chunks+chunksA, ""));\r
-}\r
-\r
-\r
-void XDKAllocationTracker::CollectFreedObjects(bool bAll, bool initPreCollect) {\r
-  clearIndividualReteiners();\r
-  if (collectRetention_) {\r
-    XDKSnapshotFiller filler(ids_, names_, this);\r
-    HeapSnapshotGenerator generator(heap_profiler_, NULL, NULL, NULL,\r
-                                    ids_->heap(), &filler);\r
-    generator.GenerateSnapshot();\r
-  }\r
-\r
-  Heap *heap = ids_->heap();\r
-  if (!heap) {\r
-    return;\r
-  }\r
-\r
-  unsigned int ts = GetTimeDelta();\r
-  if (bAll) {\r
-    ts += RETAINED_DELTA;\r
-  }\r
-\r
-  // CDT heap profiler calls CollectAllGarbage twice because after the first\r
-  // pass there are weak retained object not collected, but due to perf issues\r
-  // and because we do garbage collection regularly, we leave here only one call\r
-  // only for strict collection like in test where we need to make sure that\r
-  // object is definitely collected, we collect twice\r
-  heap->CollectAllGarbage(\r
-      Heap::kMakeHeapIterableMask,\r
-      "XDKAllocationTracker::CollectFreedObjects");\r
-  if (strict_collection_) {\r
-    heap->CollectAllGarbage(\r
-        Heap::kMakeHeapIterableMask,\r
-        "XDKAllocationTracker::CollectFreedObjects");\r
-  }\r
-  std::map<Address, RefSet> individualReteiners;\r
-\r
-  // TODO(amalyshe): check what DisallowHeapAllocation no_alloc means because in\r
-  // standalone v8 this part is crashed if DisallowHeapAllocation is defined\r
-  // DisallowHeapAllocation no_alloc;\r
-  if (!bAll) {\r
-    HeapIterator iterator(heap);\r
-    HeapObject* obj = iterator.next();\r
-    for (;\r
-         obj != NULL;\r
-         obj = iterator.next()) {\r
-      Address addr = obj->address();\r
-\r
-      PostCollectedInfo* info = runtime_info_->FindPostCollectedInfo(addr);\r
-      if (!info) {\r
-        // if we don't find info, we consider it as pre collection allocated\r
-        // object. need to add to the full picture for retentions\r
-        if (initPreCollect) {\r
-          info = runtime_info_->AddPreCollectionInfo(addr, obj->Size());\r
-        }\r
-      }\r
-\r
-      if (info) {\r
-        info->dirty_ = true;\r
-      }\r
-      // check of the class name and its initialization\r
-      if ((info && info->className_ == (unsigned)-1) || !info) {\r
-        InitClassName(addr, ts, obj->Size());\r
-      }\r
-    }\r
-  }\r
-\r
-  if (collectRetention_) {\r
-    std::map<Address, RefSet>::const_iterator citir =\r
-        individualReteiners_.begin();\r
-    while (citir != individualReteiners_.end()) {\r
-      PostCollectedInfo* infoChild =\r
-          runtime_info_->FindPostCollectedInfo(citir->first);\r
-      if (infoChild) {\r
-        RefId rfId;\r
-        rfId.stackId_ = infoChild->stackId_;\r
-        rfId.classId_ = infoChild->className_;\r
-\r
-        references_->addReference(rfId, citir->second, infoChild->timeStamp_);\r
-      }\r
-      citir++;\r
-    }\r
-  }\r
-\r
-  runtime_info_->CollectGarbaged(ts);\r
-}\r
-\r
-\r
-void XDKAllocationTracker::SerializeChunk(std::string* symbols,\r
-                                          std::string* types,\r
-                                          std::string* frames,\r
-                                          std::string* chunks,\r
-                                          std::string* retentions,\r
-                                          bool final) {\r
-  if (final) {\r
-    *symbols = symbols_->SerializeChunk();\r
-    *types = classNames_->SerializeChunk();\r
-  }\r
-  *frames = collectedStacks_->SerializeChunk();\r
-  *chunks = aggregated_chunks_->SerializeChunk();\r
-\r
-  *retentions = references_->serialize();\r
-  std::stringstream retentionsT;\r
-  retentionsT << GetTimeDelta() << std::endl << retentions->c_str();\r
-  *retentions = retentionsT.str();\r
-  references_->clear();\r
-}\r
-\r
-\r
-OutputStream::WriteResult XDKAllocationTracker::SendChunk(\r
-    OutputStream* stream) {\r
-  // go over all aggregated_ and send data to the stream\r
-  std::string symbols, types, frames, chunks, retentions;\r
-  SerializeChunk(&symbols, &types, &frames, &chunks, &retentions);\r
-\r
-  OutputStream::WriteResult ret = stream->WriteHeapXDKChunk(\r
-      symbols.c_str(), symbols.length(),\r
-      frames.c_str(), frames.length(),\r
-      types.c_str(), types.length(),\r
-      chunks.c_str(), chunks.length(),\r
-      retentions.c_str(), retentions.length());\r
-  return ret;\r
-}\r
-\r
-\r
-unsigned XDKAllocationTracker::GetTraceNodeId(Address address) {\r
-    PostCollectedInfo* info = runtime_info_->FindPostCollectedInfo(address);\r
-    if (info) {\r
-      return info->stackId_;\r
-    } else {\r
-      return AllocatedBeforeCollectionFrame_;\r
-    }\r
-}\r
-\r
-\r
-void XDKAllocationTracker::clearIndividualReteiners() {\r
-  individualReteiners_.clear();\r
-}\r
-\r
-\r
-std::map<Address, RefSet>* XDKAllocationTracker::GetIndividualReteiners() {\r
-  return &individualReteiners_;\r
-}\r
-\r
-\r
-unsigned XDKAllocationTracker::FindClassName(Address address) {\r
-  PostCollectedInfo* info = runtime_info_->FindPostCollectedInfo(address);\r
-  if (info) {\r
-    return info->className_;\r
-  } else {\r
-    return (unsigned)-1;\r
-  }\r
-}\r
-\r
-\r
-unsigned XDKAllocationTracker::InitClassName(Address address, unsigned ts,\r
-                                             unsigned size) {\r
-  unsigned id = -2;\r
-  PostCollectedInfo* info = runtime_info_->FindPostCollectedInfo(address);\r
-  if (!info) {\r
-    info = runtime_info_->AddPostCollectedInfo(address, ts);\r
-    info->className_ = -1;\r
-    info->stackId_ = outOfContextFrame_;\r
-    info->timeStamp_ = ts;\r
-    info->size_ = size;\r
-  }\r
-  if (info->className_ == (unsigned)-1) {\r
-    String* str = classNames_->GetConstructorName(address);\r
-    if (str) {\r
-      // get const char*, it's safe because pointer will be retained in the\r
-      // name_ until it is destroyed\r
-      id = classNames_->registerName(names_->GetName(str));\r
-    }\r
-  }\r
-  info->className_ = id;\r
-  return id;\r
-}\r
-\r
-\r
-unsigned XDKAllocationTracker::FindOrInitClassName(Address address,\r
-                                                   unsigned ts) {\r
-  unsigned id = FindClassName(address);\r
-  if (id == (unsigned)-1) {\r
-    // TODO(amalyshe) check if 0 size here is appropriate\r
-    id = InitClassName(address, ts, 0);\r
-  }\r
-  return id;\r
-}\r
-\r
-\r
-// -----------------------------------------------------------------------------\r
-// this is almost a copy and duplication of\r
-// V8HeapExplorer::AddEntry. refactoring is impossible because\r
-// heap-snapshot-generator rely on it's structure which is not fully suitable\r
-// for us.\r
-HeapEntry* XDKSnapshotFiller::AddEntry(HeapThing ptr,\r
-                                       HeapEntriesAllocator* allocator) {\r
-  HeapObject* object = reinterpret_cast<HeapObject*>(ptr);\r
-  if (object->IsJSFunction()) {\r
-    JSFunction* func = JSFunction::cast(object);\r
-    SharedFunctionInfo* shared = func->shared();\r
-    const char* name = shared->bound() ? "native_bind" :\r
-        names_->GetName(String::cast(shared->name()));\r
-    return AddEntry(ptr, object, HeapEntry::kClosure, name);\r
-  } else if (object->IsJSRegExp()) {\r
-    JSRegExp* re = JSRegExp::cast(object);\r
-    return AddEntry(ptr, object,\r
-                    HeapEntry::kRegExp,\r
-                    names_->GetName(re->Pattern()));\r
-  } else if (object->IsJSObject()) {\r
-    return AddEntry(ptr, object, HeapEntry::kObject, "");\r
-  } else if (object->IsString()) {\r
-    String* string = String::cast(object);\r
-    if (string->IsConsString())\r
-      return AddEntry(ptr, object,\r
-                      HeapEntry::kConsString,\r
-                      "(concatenated string)");\r
-    if (string->IsSlicedString())\r
-      return AddEntry(ptr, object,\r
-                      HeapEntry::kSlicedString,\r
-                      "(sliced string)");\r
-    return AddEntry(ptr, object,\r
-                    HeapEntry::kString,\r
-                    names_->GetName(String::cast(object)));\r
-  } else if (object->IsSymbol()) {\r
-    return AddEntry(ptr, object, HeapEntry::kSymbol, "symbol");\r
-  } else if (object->IsCode()) {\r
-    return AddEntry(ptr, object, HeapEntry::kCode, "");\r
-  } else if (object->IsSharedFunctionInfo()) {\r
-    String* name = String::cast(SharedFunctionInfo::cast(object)->name());\r
-    return AddEntry(ptr, object,\r
-                    HeapEntry::kCode,\r
-                    names_->GetName(name));\r
-  } else if (object->IsScript()) {\r
-    Object* name = Script::cast(object)->name();\r
-    return AddEntry(ptr, object,\r
-                    HeapEntry::kCode,\r
-                    name->IsString()\r
-                        ? names_->GetName(String::cast(name))\r
-                        : "");\r
-  } else if (object->IsNativeContext()) {\r
-    return AddEntry(ptr, object, HeapEntry::kHidden, "system / NativeContext");\r
-  } else if (object->IsContext()) {\r
-    return AddEntry(ptr, object, HeapEntry::kObject, "system / Context");\r
-  } else if (object->IsFixedArray() ||\r
-             object->IsFixedDoubleArray() ||\r
-             object->IsByteArray() ||\r
-             object->IsExternalArray()) {\r
-    return AddEntry(ptr, object, HeapEntry::kArray, "");\r
-  } else if (object->IsHeapNumber()) {\r
-    return AddEntry(ptr, object, HeapEntry::kHeapNumber, "number");\r
-  }\r
-\r
-  return AddEntry(ptr, object, HeapEntry::kHidden, "system / NOT SUPORTED YET");\r
-}\r
-\r
-\r
-HeapEntry* XDKSnapshotFiller::AddEntry(HeapThing thing,\r
-                    HeapObject* object,\r
-                    HeapEntry::Type type,\r
-                    const char* name) {\r
-  Address address = object->address();\r
-  unsigned trace_node_id = 0;\r
-  trace_node_id = allocation_tracker_->GetTraceNodeId(address);\r
-\r
-  // cannot store pointer in the map because List reallcoates content regularly\r
-  // and the only  one way to find the entry - by index. so, index is cached in\r
-  // the map\r
-  // TODO(amalyshe): need to reuse type. it seems it is important\r
-  HeapEntry entry(NULL, &heap_entries_list_, type, name, 0, 0,\r
-                  trace_node_id);\r
-  heap_entries_list_.Add(entry);\r
-  HeapEntry* pEntry = &heap_entries_list_.last();\r
-\r
-  HashMap::Entry* cache_entry = heap_entries_.Lookup(thing, Hash(thing), true);\r
-  DCHECK(cache_entry->value == NULL);\r
-  int index = pEntry->index();\r
-  cache_entry->value = reinterpret_cast<void*>(static_cast<intptr_t>(index));\r
-\r
-  // TODO(amalyshe): it seems this storage might be optimized\r
-  HashMap::Entry* address_entry = index_to_address_.Lookup(\r
-      reinterpret_cast<void*>(index+1), HashInt(index+1), true);\r
-  address_entry->value = reinterpret_cast<void*>(address);\r
-\r
-  return pEntry;\r
-}\r
-\r
-\r
-HeapEntry* XDKSnapshotFiller::FindEntry(HeapThing thing) {\r
-  HashMap::Entry* cache_entry = heap_entries_.Lookup(thing, Hash(thing), false);\r
-  if (cache_entry == NULL) return NULL;\r
-  return &heap_entries_list_[static_cast<int>(\r
-      reinterpret_cast<intptr_t>(cache_entry->value))];\r
-}\r
-\r
-\r
-HeapEntry* XDKSnapshotFiller::FindOrAddEntry(HeapThing ptr,\r
-                                             HeapEntriesAllocator* allocator) {\r
-  HeapEntry* entry = FindEntry(ptr);\r
-  return entry != NULL ? entry : AddEntry(ptr, allocator);\r
-}\r
-\r
-\r
-void XDKSnapshotFiller::SetIndexedReference(HeapGraphEdge::Type type,\r
-    int parent,\r
-    int index,\r
-    HeapEntry* child_entry) {\r
-  if (child_entry->trace_node_id() < 3) {\r
-    return;\r
-  }\r
-  HashMap::Entry* address_entry_child = index_to_address_.Lookup(\r
-      reinterpret_cast<void*>(child_entry->index()+1),\r
-      HashInt(child_entry->index()+1), false);\r
-  DCHECK(address_entry_child != NULL);\r
-  if (!address_entry_child) {\r
-    return;\r
-  }\r
-\r
-  Address child_addr = reinterpret_cast<Address>(address_entry_child->value);\r
-\r
-  std::map<Address, RefSet>* individualReteiners =\r
-      allocation_tracker_->GetIndividualReteiners();\r
-  // get the parent's address, constructor name and form the RefId\r
-  HashMap::Entry* address_entry = index_to_address_.Lookup(\r
-      reinterpret_cast<void*>(parent+1), HashInt(parent+1), false);\r
-  DCHECK(address_entry != NULL);\r
-  if (!address_entry) {\r
-    return;\r
-  }\r
-  HeapEntry* parent_entry = &(heap_entries_list_[parent]);\r
-  Address parent_addr = reinterpret_cast<Address>(address_entry->value);\r
-  RefId parent_ref_id;\r
-  parent_ref_id.stackId_ = parent_entry->trace_node_id();\r
-  parent_ref_id.classId_ =\r
-      allocation_tracker_->FindOrInitClassName(parent_addr, 0);\r
-\r
-  std::stringstream str;\r
-  str << index << " element in Array";\r
-  parent_ref_id.field_ = str.str();\r
-\r
-  (*individualReteiners)[child_addr].references_.insert(parent_ref_id);\r
-}\r
-\r
-\r
-void XDKSnapshotFiller::SetIndexedAutoIndexReference(HeapGraphEdge::Type type,\r
-    int parent,\r
-    HeapEntry* child_entry) {\r
-}\r
-\r
-\r
-void XDKSnapshotFiller::SetNamedReference(HeapGraphEdge::Type type,\r
-    int parent,\r
-    const char* reference_name,\r
-    HeapEntry* child_entry) {\r
-  if (child_entry->trace_node_id() < 3) {\r
-    return;\r
-  }\r
-\r
-  std::map<Address, RefSet>* individualReteiners =\r
-      allocation_tracker_->GetIndividualReteiners();\r
-  // get the parent's address, constructor name and form the RefId\r
-  HashMap::Entry* address_entry = index_to_address_.Lookup(\r
-      reinterpret_cast<void*>(parent+1), HashInt(parent+1), false);\r
-  DCHECK(address_entry != NULL);\r
-  if (!address_entry) {\r
-    return;\r
-  }\r
-  HeapEntry* parent_entry = &(heap_entries_list_[parent]);\r
-  Address parent_addr = reinterpret_cast<Address>(address_entry->value);\r
-  RefId parent_ref_id;\r
-  parent_ref_id.stackId_ = parent_entry->trace_node_id();\r
-  // TODO(amalyshe): need to get access to classNames_\r
-  parent_ref_id.classId_ =\r
-      allocation_tracker_->FindOrInitClassName(parent_addr, 0);\r
-  parent_ref_id.field_ = reference_name;\r
-\r
-  HashMap::Entry* address_entry_child = index_to_address_.Lookup(\r
-      reinterpret_cast<void*>(child_entry->index()+1),\r
-      HashInt(child_entry->index()+1), false);\r
-  DCHECK(address_entry_child != NULL);\r
-  if (!address_entry_child) {\r
-    return;\r
-  }\r
-  Address child_addr = reinterpret_cast<Address>(address_entry_child->value);\r
-\r
-  (*individualReteiners)[child_addr].references_.insert(parent_ref_id);\r
-}\r
-\r
-\r
-void XDKSnapshotFiller::SetNamedAutoIndexReference(HeapGraphEdge::Type type,\r
-                                int parent,\r
-                                HeapEntry* child_entry) {\r
-}\r
-\r
-\r
-}\r
-}  // namespace v8::internal\r
+// 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 <sstream>
+#include <string>
+
+#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<unsigned> stack_ooc;
+  stack_ooc.Add(symbols_->registerSymInfo(1, "OutOfContext", "NoSource",
+                                          0, 0));
+  outOfContextFrame_ = collectedStacks_->registerStack(stack_ooc);
+
+  List<unsigned> 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<unsigned int>(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<unsigned> 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<Address, RefSet> 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<Address, RefSet>::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<Address, RefSet>* 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<HeapObject*>(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<void*>(static_cast<intptr_t>(index));
+
+  // TODO(amalyshe): it seems this storage might be optimized
+  HashMap::Entry* address_entry = index_to_address_.Lookup(
+      reinterpret_cast<void*>(index+1), HashInt(index+1), true);
+  address_entry->value = reinterpret_cast<void*>(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<int>(
+      reinterpret_cast<intptr_t>(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<void*>(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>(address_entry_child->value);
+
+  std::map<Address, RefSet>* 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<void*>(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>(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<Address, RefSet>* 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<void*>(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>(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<void*>(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>(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
index 79384e9..d5305c5 100644 (file)
-// Copyright 2014 the V8 project authors. All rights reserved.\r
-// Use of this source code is governed by a BSD-style license that can be\r
-// found in the LICENSE file.\r
-\r
-#ifndef V8_XDK_ALLOCATION_H_\r
-#define V8_XDK_ALLOCATION_H_\r
-\r
-#include <map>\r
-#include <string>\r
-#include "src/base/platform/time.h"\r
-\r
-namespace v8 {\r
-namespace internal {\r
-\r
-class HeapObjectsMap;\r
-class HeapEventXDK;\r
-class ClassNames;\r
-class ShadowStack;\r
-class SymbolsStorage;\r
-class AggregatedChunks;\r
-class RuntimeInfo;\r
-class References;\r
-class RefSet;\r
-\r
-\r
-class XDKSnapshotFiller: public SnapshotFiller {\r
- public:\r
-  explicit XDKSnapshotFiller(HeapObjectsMap* heap_object_map,\r
-                             StringsStorage* names,\r
-                             XDKAllocationTracker* allocation_tracker)\r
-      : names_(names),\r
-      heap_object_map_(heap_object_map),\r
-      allocation_tracker_(allocation_tracker),\r
-      heap_entries_(HashMap::PointersMatch),\r
-      index_to_address_(HashMap::PointersMatch) {}\r
-  virtual ~XDKSnapshotFiller() {}\r
-\r
-  HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator);\r
-  HeapEntry* FindEntry(HeapThing thing);\r
-  HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator);\r
-  void SetIndexedReference(HeapGraphEdge::Type type,\r
-                           int parent,\r
-                           int index,\r
-                           HeapEntry* child_entry);\r
-  void SetIndexedAutoIndexReference(HeapGraphEdge::Type type,\r
-                                    int parent,\r
-                                    HeapEntry* child_entry);\r
-  void SetNamedReference(HeapGraphEdge::Type type,\r
-                         int parent,\r
-                         const char* reference_name,\r
-                         HeapEntry* child_entry);\r
-  void SetNamedAutoIndexReference(HeapGraphEdge::Type type,\r
-                                  int parent,\r
-                                  HeapEntry* child_entry);\r
-\r
- private:\r
-  StringsStorage* names_;\r
-  HeapObjectsMap* heap_object_map_;\r
-  XDKAllocationTracker* allocation_tracker_;\r
-  HashMap heap_entries_;\r
-  HashMap index_to_address_;\r
-\r
-\r
-  List<HeapEntry> heap_entries_list_;\r
-\r
-  HeapEntry* AddEntry(HeapThing thing,\r
-                      HeapObject* object,\r
-                      HeapEntry::Type type,\r
-                      const char* name);\r
-\r
-  static uint32_t Hash(HeapThing thing) {\r
-    return ComputeIntegerHash(\r
-        static_cast<uint32_t>(reinterpret_cast<uintptr_t>(thing)),\r
-        v8::internal::kZeroHashSeed);\r
-  }\r
-  static uint32_t HashInt(int key) {\r
-    return ComputeIntegerHash(key, v8::internal::kZeroHashSeed);\r
-  }\r
-};\r
-\r
-\r
-class XDKAllocationTracker {\r
- public:\r
-  XDKAllocationTracker(HeapProfiler* heap_profiler,\r
-                       HeapObjectsMap* ids,\r
-                       StringsStorage* names,\r
-                       int stackDepth,\r
-                       bool collectRetention,\r
-                       bool strict_collection);\r
-  ~XDKAllocationTracker();\r
-\r
-  void OnAlloc(Address addr, int size);\r
-  void OnMove(Address from, Address to, int size);\r
-  void CollectFreedObjects(bool bAll = false, bool initPreCollect = false);\r
-  HeapEventXDK* stopTracking();\r
-  OutputStream::WriteResult  SendChunk(OutputStream* stream);\r
-  unsigned GetTraceNodeId(Address address);\r
-  void clearIndividualReteiners();\r
-  std::map<Address, RefSet>* GetIndividualReteiners();\r
-\r
-  unsigned FindOrInitClassName(Address address, unsigned ts);\r
-\r
- private:\r
-  static const int RETAINED_DELTA = 1000;\r
-\r
-  // external object\r
-  HeapProfiler* heap_profiler_;\r
-  HeapObjectsMap* ids_;\r
-  StringsStorage* names_;\r
-\r
-  AggregatedChunks* aggregated_chunks_;\r
-  RuntimeInfo* runtime_info_;\r
-  void SerializeChunk(std::string* symbols, std::string* types,\r
-                      std::string* frames, std::string* chunks,\r
-                      std::string* retentions, bool final = false);\r
-\r
-  unsigned FindClassName(Address address);\r
-  unsigned InitClassName(Address address, unsigned ts, unsigned size);\r
-\r
-  SymbolsStorage* symbols_;\r
-  ShadowStack* collectedStacks_;\r
-  ClassNames* classNames_;\r
-\r
-  unsigned outOfContextFrame_;\r
-  unsigned AllocatedBeforeCollectionFrame_;\r
-\r
-  v8::base::Time baseTime_;\r
-  unsigned latest_delta_;\r
-  unsigned int GetTimeDelta();\r
-\r
-  int stackDepth_;\r
-  bool collectRetention_;\r
-  bool strict_collection_;\r
-  References* references_;\r
-  std::map<Address, RefSet> individualReteiners_;\r
-};\r
-\r
-\r
-class HeapEventXDK {\r
- public:\r
-  HeapEventXDK(unsigned int duration,\r
-               const std::string& symbols, const std::string& types,\r
-               const std::string& frames, const std::string& chunks,\r
-               const std::string& retentions) :\r
-    symbols_(symbols), types_(types), frames_(frames), chunks_(chunks),\r
-    duration_(duration), retentions_(retentions) {\r
-  }\r
-\r
-  unsigned int duration() const {return duration_; }\r
-  const char* symbols() const { return symbols_.c_str(); }\r
-  const char* types() const { return types_.c_str(); }\r
-  const char* frames() const { return frames_.c_str(); }\r
-  const char* chunks() const { return chunks_.c_str(); }\r
-  const char* retentions()  const { return retentions_.c_str(); }\r
-\r
- private:\r
-  std::string symbols_;\r
-  std::string types_;\r
-  std::string frames_;\r
-  std::string chunks_;\r
-  unsigned int duration_;\r
-  std::string retentions_;\r
-  DISALLOW_COPY_AND_ASSIGN(HeapEventXDK);\r
-};\r
-\r
-} }  // namespace v8::internal\r
-\r
-#endif  // V8_XDK_ALLOCATION_H_\r
+// 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 <map>
+#include <string>
+#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<HeapEntry> 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<uint32_t>(reinterpret_cast<uintptr_t>(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<Address, RefSet>* 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<Address, RefSet> 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_
index b17eb95..d05dd6d 100644 (file)
-// Copyright 2014 the V8 project authors. All rights reserved.\r
-// Use of this source code is governed by a BSD-style license that can be\r
-// found in the LICENSE file.\r
-\r
-#include "src/v8.h"\r
-\r
-#include "src/frames-inl.h"\r
-#include "src/xdk-utils.h"\r
-\r
-namespace v8 {\r
-namespace internal {\r
-\r
-static bool AddressesMatch(void* key1, void* key2) {\r
-  return key1 == key2;\r
-}\r
-\r
-\r
-static uint32_t CharAddressHash(char* addr) {\r
-  return ComputeIntegerHash(static_cast<uint32_t>(\r
-      reinterpret_cast<uintptr_t>(addr)),\r
-      v8::internal::kZeroHashSeed);\r
-}\r
-\r
-\r
-static uint32_t AddressHash(Address addr) {\r
-  return ComputeIntegerHash(static_cast<uint32_t>(\r
-      reinterpret_cast<uintptr_t>(addr)),\r
-      v8::internal::kZeroHashSeed);\r
-}\r
-\r
-\r
-ClassNames::ClassNames(StringsStorage* names)\r
-    : counter_(0),\r
-    char_to_idx_(AddressesMatch),\r
-    names_(names) {\r
-}\r
-\r
-\r
-unsigned ClassNames::registerName(const char* name) {\r
-  // since const char is retained outside and cannot be moved, we rely on this\r
-  // and just compare the pointers. It should be enough for the strings from the\r
-  // only one StringStorage\r
-  unsigned counter;\r
-  HashMap::Entry* entry = char_to_idx_.Lookup(const_cast<char*>(name),\r
-      CharAddressHash(const_cast<char*>(name)),\r
-      true);\r
-  if (entry->value == NULL) {\r
-    counter = ++counter_;\r
-    entry->value = reinterpret_cast<void*>(counter);\r
-  } else {\r
-    counter = static_cast<unsigned>(reinterpret_cast<uintptr_t>(entry->value));\r
-  }\r
-  return counter;\r
-}\r
-\r
-\r
-std::string ClassNames::SerializeChunk() {\r
-  std::stringstream serialized;\r
-  for (HashMap::Entry* p = char_to_idx_.Start(); p != NULL;\r
-      p = char_to_idx_.Next(p)) {\r
-    serialized << static_cast<unsigned>(\r
-        reinterpret_cast<uintptr_t>(p->value)) << "," <<\r
-        reinterpret_cast<char*>(p->key) << std::endl;\r
-  }\r
-\r
-  return serialized.str();\r
-}\r
-\r
-\r
-String* ClassNames::GetConstructorName(Address address) {\r
-  HeapObject *heap_object = HeapObject::FromAddress(address);\r
-  bool is_js_object = heap_object->IsJSObject();\r
-  if (!is_js_object) {\r
-    // TODO(amalyshe): look for another function for taking the class name\r
-    // String* constructor_name = object2->constructor_name();\r
-    return NULL;\r
-  }\r
-  JSObject* object = JSObject::cast(heap_object);\r
-  Heap* heap = object->GetHeap();\r
-  if (object->IsJSFunction()) return heap->closure_string();\r
-  return object->constructor_name();\r
-}\r
-\r
-\r
-// -----------------------------------------------------------------------------\r
-ShadowStack::ShadowStack() {\r
-  last_index_ = 1;\r
-  serializedCounter_ = last_index_;\r
-  root_.index_ = 0;\r
-  root_.parent_ = NULL;\r
-  root_.callsite_ = 0;\r
-}\r
-\r
-\r
-ShadowStack::~ShadowStack() {\r
-  // erasing all objects from the current container\r
-  std::map<unsigned, CallTree*>::iterator eit = allNodes_.begin();\r
-  while (eit != allNodes_.end()) {\r
-    delete eit->second;\r
-    eit++;\r
-  }\r
-}\r
-\r
-\r
-unsigned ShadowStack::registerStack(const List<unsigned>& shadow_stack_) {\r
-    // look for the latest node\r
-    CallTree* pNode = &root_;\r
-    // go over all entries and add them to the tree if they are not in the map\r
-    int i, j;\r
-    for (i = shadow_stack_.length()-1; i != -1; i--) {\r
-      std::map<unsigned, CallTree*>::iterator it =\r
-          pNode->children_.find(shadow_stack_[i]);\r
-      if (it == pNode->children_.end())\r
-          break;\r
-      pNode = it->second;\r
-    }\r
-    // verification if we need to add something or not\r
-    for (j = i; j != -1; j--) {\r
-      CallTree* pNodeTmp = new CallTree;\r
-      pNodeTmp->index_ = last_index_++;\r
-      pNodeTmp->parent_ = pNode;\r
-      pNodeTmp->callsite_ = shadow_stack_[j];\r
-      pNode->children_[shadow_stack_[j]] = pNodeTmp;\r
-      allNodes_[pNodeTmp->index_] = pNodeTmp;\r
-      pNode = pNodeTmp;\r
-    }\r
-    return pNode->index_;\r
-}\r
-\r
-\r
-std::string ShadowStack::SerializeChunk() {\r
-  std::stringstream str;\r
-  std::map<unsigned, CallTree*>::iterator it =\r
-      allNodes_.find(serializedCounter_);\r
-  while (it!= allNodes_.end()) {\r
-    str << it->first << "," << it->second->callsite_ << "," <<\r
-        it->second->parent_->index_ << std::endl;\r
-    it++;\r
-  }\r
-\r
-  serializedCounter_ = last_index_;\r
-  return str.str();\r
-}\r
-\r
-\r
-// -----------------------------------------------------------------------------\r
-static bool SymInfoMatch(void* key1, void* key2) {\r
-  SymInfoKey* key_c1 = reinterpret_cast<SymInfoKey*>(key1);\r
-  SymInfoKey* key_c2 = reinterpret_cast<SymInfoKey*>(key2);\r
-  return *key_c1 == *key_c2;\r
-}\r
-\r
-\r
-static uint32_t SymInfoHash(const SymInfoKey& key) {\r
-  uint32_t hash = 0;\r
-  // take the low 16 bits of function_id_\r
-  hash |= (key.function_id_ & 0xffff);\r
-  // take the low 8 bits of line_ and column_ and init highest bits\r
-  hash |= ((key.line_ & 0xff) << 16);\r
-  hash |= ((key.column_ & 0xff) << 14);\r
-\r
-  return hash;\r
-}\r
-\r
-\r
-struct SymbolCached {\r
-  unsigned int symbol_id_;\r
-  uintptr_t function_;\r
-};\r
-\r
-\r
-SymbolsStorage::SymbolsStorage(Heap* heap, StringsStorage* names) :\r
-  symbols_(SymInfoMatch),\r
-  curSym_(1),\r
-  sym_info_hash_(AddressesMatch),\r
-  heap_(heap),\r
-  names_(names) {\r
-  reserved_key_ = new SymInfoKey();\r
-}\r
-\r
-\r
-SymbolsStorage::~SymbolsStorage() {\r
-  // go over map and delete all keys and values\r
-  for (HashMap::Entry* p = symbols_.Start(); p != NULL; p = symbols_.Next(p)) {\r
-    delete reinterpret_cast<SymInfoValue*>(p->value);\r
-    delete reinterpret_cast<SymInfoKey*>(p->key);\r
-  }\r
-  delete reserved_key_;\r
-}\r
-\r
-\r
-unsigned SymbolsStorage::registerSymInfo(size_t functionId,\r
-                                         std::string functionName,\r
-                                         std::string sourceName,\r
-                                         unsigned line,\r
-                                         unsigned column) {\r
-  if (sourceName.empty()) {\r
-    sourceName = "unknown";\r
-  }\r
-\r
-  reserved_key_->function_id_ = functionId;\r
-  reserved_key_->line_ = line;\r
-  reserved_key_->column_ = column;\r
-\r
-  HashMap::Entry* entry = symbols_.Lookup(reserved_key_,\r
-                                          SymInfoHash(*reserved_key_), true);\r
-  if (entry->value) {\r
-    return reinterpret_cast<SymInfoValue*>(entry->value)->symId_;\r
-  }\r
-\r
-  // else initialize by new one\r
-  SymInfoValue* value = new SymInfoValue;\r
-  value->symId_ = curSym_++;\r
-  value->funcName_ = functionName;\r
-  value->sourceFile_ = sourceName;\r
-  entry->value = value;\r
-\r
-  // compensation for registered one\r
-  reserved_key_ = new SymInfoKey();\r
-\r
-  return value->symId_;\r
-}\r
-\r
-\r
-std::string SymbolsStorage::SerializeChunk() {\r
-  std::stringstream serialized;\r
-  for (HashMap::Entry* p = symbols_.Start(); p != NULL; p = symbols_.Next(p)) {\r
-    SymInfoValue* v = reinterpret_cast<SymInfoValue*>(p->value);\r
-    SymInfoKey* k = reinterpret_cast<SymInfoKey*>(p->key);\r
-    serialized << v->symId_ << "," << k->function_id_ << "," <<\r
-        v->funcName_ << "," << v->sourceFile_ << "," <<\r
-        k->line_ << "," << k->column_ << std::endl;\r
-  }\r
-\r
-  return serialized.str();\r
-}\r
-\r
-\r
-unsigned SymbolsStorage::FindOrRegisterFrame(JavaScriptFrame* frame) {\r
-  SharedFunctionInfo *shared = frame->function()->shared();\r
-  DCHECK(shared);\r
-  Isolate *isolate = heap_->isolate();\r
-\r
-  Address pc = frame->pc();\r
-  unsigned int symbolId = 0;\r
-\r
-  // We don't rely on the address only. Since this is JIT based language,\r
-  // the address might be occupied by other function\r
-  // thus we are verifying if the same function takes this place\r
-  // before we take symbol info from the cache\r
-  HashMap::Entry* sym_entry = sym_info_hash_.Lookup(\r
-          reinterpret_cast<void*>(pc), AddressHash(pc), true);\r
-  if (sym_entry->value == NULL ||\r
-      (reinterpret_cast<SymbolCached*>(sym_entry->value)->function_ !=\r
-        reinterpret_cast<uintptr_t>(frame->function()))) {\r
-    if (sym_entry->value) {\r
-      delete reinterpret_cast<SymbolCached*>(sym_entry->value);\r
-    }\r
-\r
-    const char *s = names_->GetFunctionName(shared->DebugName());\r
-    // trying to get the source name and line#\r
-    Code *code = Code::cast(isolate->FindCodeObject(pc));\r
-    if (code) {\r
-      int source_pos = code->SourcePosition(pc);\r
-      Object *maybe_script = shared->script();\r
-      if (maybe_script && maybe_script->IsScript()) {\r
-        Handle<Script> script(Script::cast(maybe_script));\r
-        if (!script.is_null()) {\r
-          int line = script->GetLineNumber(source_pos) + 1;\r
-          // TODO(amalyshe): check if this can be used:\r
-          // int line = GetScriptLineNumberSafe(script, source_pos) + 1;\r
-          // TODO(amalyshe): add column number getting\r
-          int column = 0;  // GetScriptColumnNumber(script, source_pos);\r
-          Object *script_name_raw = script->name();\r
-          if (script_name_raw->IsString()) {\r
-            String *script_name = String::cast(script->name());\r
-            SmartArrayPointer<char> c_script_name =\r
-              script_name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);\r
-            symbolId = registerSymInfo((size_t)frame->function(), s,\r
-                                       c_script_name.get(), line, column);\r
-          }\r
-        }\r
-      }\r
-    }\r
-    if (symbolId == 0) {\r
-      symbolId = registerSymInfo((size_t)frame->function(), s, "", 0, 0);\r
-    }\r
-\r
-    SymbolCached* symCached = new SymbolCached;\r
-    symCached->function_ = reinterpret_cast<uintptr_t>(frame->function());\r
-    symCached->symbol_id_ = symbolId;\r
-    sym_entry->value = symCached;\r
-  } else {\r
-    symbolId = reinterpret_cast<SymbolCached*>(sym_entry->value)->symbol_id_;\r
-  }\r
-  return symbolId;\r
-}\r
-\r
-\r
-// -----------------------------------------------------------------------------\r
-RuntimeInfo::RuntimeInfo(AggregatedChunks* aggregated_chunks):\r
-  working_set_hash_(AddressesMatch),\r
-  aggregated_chunks_(aggregated_chunks),\r
-  AllocatedBeforeCollectionFrame_(0) {\r
-}\r
-\r
-\r
-PostCollectedInfo* RuntimeInfo::FindPostCollectedInfo(Address addr) {\r
-  HashMap::Entry* entry = working_set_hash_.Lookup(\r
-          reinterpret_cast<void*>(addr), AddressHash(addr), false);\r
-  if (entry && entry->value) {\r
-    PostCollectedInfo* info =\r
-        reinterpret_cast<PostCollectedInfo*>(entry->value);\r
-    return info;\r
-  }\r
-  return NULL;\r
-}\r
-\r
-\r
-PostCollectedInfo* RuntimeInfo::AddPostCollectedInfo(Address addr,\r
-                                                    unsigned time_delta,\r
-                                                    PostCollectedInfo* info) {\r
-  PostCollectedInfo* info_new = NULL;\r
-  if (!info) {\r
-    info_new = new PostCollectedInfo;\r
-  } else {\r
-    info_new = info;\r
-  }\r
-\r
-  HashMap::Entry* entry = working_set_hash_.Lookup(\r
-          reinterpret_cast<void*>(addr), AddressHash(addr), true);\r
-  DCHECK(entry);\r
-  if (entry->value != NULL) {\r
-    // compensation of the wrong deallocation place\r
-    // we were not able to work the GC epilogue callback because GC is not\r
-    // iteratable in the prologue\r
-    // thus we need to mark the object as freed\r
-    PostCollectedInfo* info_old =\r
-        static_cast<PostCollectedInfo*>(entry->value);\r
-    aggregated_chunks_->addObjectToAggregated(info_old, time_delta);\r
-    delete info_old;\r
-  }\r
-\r
-  entry->value = info_new;\r
-  return info_new;\r
-}\r
-\r
-\r
-PostCollectedInfo* RuntimeInfo::AddPreCollectionInfo(Address addr,\r
-                                                     unsigned size) {\r
-  PostCollectedInfo* info = AddPostCollectedInfo(addr);\r
-  info->size_ = size;\r
-  info->timeStamp_ = 0;\r
-  info->stackId_ = AllocatedBeforeCollectionFrame_;\r
-  info->className_ = (unsigned)-1;\r
-  return info;\r
-}\r
-\r
-\r
-void RuntimeInfo::RemoveInfo(Address addr) {\r
-  working_set_hash_.Remove(reinterpret_cast<void*>(addr), AddressHash(addr));\r
-}\r
-\r
-\r
-void RuntimeInfo::InitABCFrame(unsigned abc_frame) {\r
-  AllocatedBeforeCollectionFrame_ = abc_frame;\r
-}\r
-\r
-\r
-void RuntimeInfo::CollectGarbaged(unsigned ts) {\r
-  // iteration over the working_set_hash_\r
-  for (HashMap::Entry* p = working_set_hash_.Start(); p != NULL;\r
-      p = working_set_hash_.Next(p)) {\r
-    if (p->value) {\r
-      PostCollectedInfo* info = static_cast<PostCollectedInfo*>(p->value);\r
-      if (info->dirty_ == false) {\r
-        // need to care of allocated during collection.\r
-        // if timeStamp_ == 0 this object was allocated before collection\r
-        // and we don't care of it\r
-        aggregated_chunks_->addObjectToAggregated(info, ts);\r
-        delete info;\r
-        p->value = NULL;\r
-      } else {\r
-        info->dirty_ = false;\r
-      }\r
-    }\r
-  }\r
-}\r
-\r
-\r
-//------------------------------------------------------------------------------\r
-static bool AggregatedMatch(void* key1, void* key2) {\r
-  // cast to the AggregatedKey\r
-  AggregatedKey* key_c1 = reinterpret_cast<AggregatedKey*>(key1);\r
-  AggregatedKey* key_c2 = reinterpret_cast<AggregatedKey*>(key2);\r
-  return *key_c1 == *key_c2;\r
-}\r
-\r
-\r
-static uint32_t AggregatedHash(const AggregatedKey& key) {\r
-  uint32_t hash = 0;\r
-  // take the low 8 bits of stackId_\r
-  hash |= (key.stackId_ & 0xff);\r
-  // take the low 8 bits of classId_ and init hash from 8th to 15th bits\r
-  hash |= ((key.classId_ & 0xff) << 8);\r
-  // since times are well graduated it's no sense take the lowest 8 bit\r
-  // instead this we will move to 3 bits and only then take 8 bits\r
-  hash |= (((key.tsBegin_ >> 3) & 0xff) << 16);\r
-  hash |= (((key.tsBegin_ >> 3) & 0xff) << 24);\r
-  return hash;\r
-}\r
-\r
-\r
-AggregatedChunks::AggregatedChunks() :\r
-  aggregated_map_(AggregatedMatch),\r
-  bucketSize_(500) {\r
-  reserved_key_ = new AggregatedKey();\r
-}\r
-\r
-\r
-AggregatedChunks::~AggregatedChunks() {\r
-  delete reserved_key_;\r
-}\r
-\r
-\r
-void AggregatedChunks::addObjectToAggregated(PostCollectedInfo* info,\r
-                                                        unsigned td) {\r
-  reserved_key_->stackId_ = info->stackId_;\r
-  reserved_key_->classId_ = info->className_;\r
-  // get the bucket for the first time\r
-  reserved_key_->tsBegin_ = info->timeStamp_ - (info->timeStamp_ % bucketSize_);\r
-  reserved_key_->tsEnd_ = td - (td % bucketSize_);\r
-\r
-  HashMap::Entry* aggregated_entry = aggregated_map_.Lookup(reserved_key_,\r
-                                                AggregatedHash(*reserved_key_),\r
-                                                true);\r
-  if (aggregated_entry->value) {\r
-    // no need to store the latest record in the aggregated_keys_list_\r
-    AggregatedValue* value =\r
-                reinterpret_cast<AggregatedValue*>(aggregated_entry->value);\r
-    value->objects_++;\r
-    value->size_ += info->size_;\r
-  } else {\r
-    reserved_key_ = new AggregatedKey;\r
-    AggregatedValue* value = new AggregatedValue;\r
-    value->objects_ = 1;\r
-    value->size_ = info->size_;\r
-    aggregated_entry->value = value;\r
-  }\r
-}\r
-\r
-\r
-std::string AggregatedChunks::SerializeChunk() {\r
-  std::stringstream schunks;\r
-  for (HashMap::Entry* p = aggregated_map_.Start(); p != NULL;\r
-      p = aggregated_map_.Next(p)) {\r
-    if (p->key && p->value) {\r
-      AggregatedKey* key = reinterpret_cast<AggregatedKey*>(p->key);\r
-      AggregatedValue* value = reinterpret_cast<AggregatedValue*>(p->value);\r
-      schunks <<\r
-        key->tsBegin_ << "," << key->tsEnd_ << "," <<\r
-        key->stackId_ << "," << key->classId_ << "," <<\r
-        value->size_ << "," << value->objects_ << std::endl;\r
-      delete key;\r
-      delete value;\r
-    }\r
-  }\r
-\r
-  aggregated_map_.Clear();\r
-\r
-  return schunks.str();\r
-}\r
-\r
-\r
-// -----------------------------------------------------------------------------\r
-void References::addReference(const RefId& parent, const RefSet& refSet,\r
-                               int parentTime) {\r
-  // looking for the parent in the refMap_\r
-  PARENTREFMAP::iterator cit = refMap_.find(parent);\r
-  if (cit != refMap_.end()) {\r
-    REFERENCESETS& sets = cit->second;\r
-    REFERENCESETS::iterator it = sets.find(refSet);\r
-    if (it != sets.end()) {\r
-      // look for the time\r
-      TIMETOCOUNT::iterator cittc = it->second.find(parentTime);\r
-      if (cittc != it->second.end()) {\r
-        cittc->second++;\r
-      } else {\r
-        it->second[parentTime] = 1;\r
-      }\r
-    } else {\r
-      TIMETOCOUNT tc;\r
-      tc[parentTime] = 1;\r
-      sets[refSet] = tc;\r
-    }\r
-  } else {\r
-    // adding new parent, new sets\r
-    REFERENCESETS sets;\r
-    TIMETOCOUNT tc;\r
-    tc[parentTime] = 1;\r
-    sets[refSet] = tc;\r
-    refMap_[parent] = sets;\r
-  }\r
-}\r
-\r
-\r
-void References::clear() {\r
-  refMap_.clear();\r
-}\r
-\r
-\r
-std::string References::serialize() const {\r
-  std::stringstream str;\r
-  PARENTREFMAP::const_iterator citrefs = refMap_.begin();\r
-  while (citrefs != refMap_.end()) {\r
-    REFERENCESETS::const_iterator citsets = citrefs->second.begin();\r
-    while (citsets != citrefs->second.end()) {\r
-      str << citrefs->first.stackId_ << "," << citrefs->first.classId_;\r
-      // output of length, and content of TIMETOCOUNT\r
-      str << "," << citsets->second.size();\r
-      TIMETOCOUNT::const_iterator cittc = citsets->second.begin();\r
-      while (cittc != citsets->second.end()) {\r
-        str << "," << cittc->first << "," << cittc->second;\r
-        cittc++;\r
-      }\r
-      REFERENCESET::const_iterator citset = citsets->first.references_.begin();\r
-      while (citset != citsets->first.references_.end()) {\r
-        str << "," << citset->stackId_ << "," << citset->classId_<< "," <<\r
-          citset->field_;\r
-        citset++;\r
-      }\r
-      str << std::endl;\r
-      citsets++;\r
-    }\r
-    citrefs++;\r
-  }\r
-  return str.str();\r
-}\r
-\r
-\r
-} }  // namespace v8::internal\r
+// 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<uint32_t>(
+      reinterpret_cast<uintptr_t>(addr)),
+      v8::internal::kZeroHashSeed);
+}
+
+
+static uint32_t AddressHash(Address addr) {
+  return ComputeIntegerHash(static_cast<uint32_t>(
+      reinterpret_cast<uintptr_t>(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<char*>(name),
+      CharAddressHash(const_cast<char*>(name)),
+      true);
+  if (entry->value == NULL) {
+    counter = ++counter_;
+    entry->value = reinterpret_cast<void*>(counter);
+  } else {
+    counter = static_cast<unsigned>(reinterpret_cast<uintptr_t>(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<unsigned>(
+        reinterpret_cast<uintptr_t>(p->value)) << "," <<
+        reinterpret_cast<char*>(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<unsigned, CallTree*>::iterator eit = allNodes_.begin();
+  while (eit != allNodes_.end()) {
+    delete eit->second;
+    eit++;
+  }
+}
+
+
+unsigned ShadowStack::registerStack(const List<unsigned>& 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<unsigned, CallTree*>::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<unsigned, CallTree*>::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<SymInfoKey*>(key1);
+  SymInfoKey* key_c2 = reinterpret_cast<SymInfoKey*>(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<SymInfoValue*>(p->value);
+    delete reinterpret_cast<SymInfoKey*>(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<SymInfoValue*>(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<SymInfoValue*>(p->value);
+    SymInfoKey* k = reinterpret_cast<SymInfoKey*>(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<void*>(pc), AddressHash(pc), true);
+  if (sym_entry->value == NULL ||
+      (reinterpret_cast<SymbolCached*>(sym_entry->value)->function_ !=
+        reinterpret_cast<uintptr_t>(frame->function()))) {
+    if (sym_entry->value) {
+      delete reinterpret_cast<SymbolCached*>(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<Script> script(Script::cast(maybe_script));
+        if (!script.is_null()) {
+          int line = script->GetLineNumber(source_pos) + 1;
+          // TODO(amalyshe): check if this can be used:
+          // int line = GetScriptLineNumberSafe(script, source_pos) + 1;
+          // TODO(amalyshe): add column number getting
+          int column = 0;  // GetScriptColumnNumber(script, source_pos);
+          Object *script_name_raw = script->name();
+          if (script_name_raw->IsString()) {
+            String *script_name = String::cast(script->name());
+            SmartArrayPointer<char> c_script_name =
+              script_name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+            symbolId = registerSymInfo((size_t)frame->function(), s,
+                                       c_script_name.get(), line, column);
+          }
+        }
+      }
+    }
+    if (symbolId == 0) {
+      symbolId = registerSymInfo((size_t)frame->function(), s, "", 0, 0);
+    }
+
+    SymbolCached* symCached = new SymbolCached;
+    symCached->function_ = reinterpret_cast<uintptr_t>(frame->function());
+    symCached->symbol_id_ = symbolId;
+    sym_entry->value = symCached;
+  } else {
+    symbolId = reinterpret_cast<SymbolCached*>(sym_entry->value)->symbol_id_;
+  }
+  return symbolId;
+}
+
+
+// -----------------------------------------------------------------------------
+RuntimeInfo::RuntimeInfo(AggregatedChunks* aggregated_chunks):
+  working_set_hash_(AddressesMatch),
+  aggregated_chunks_(aggregated_chunks),
+  AllocatedBeforeCollectionFrame_(0) {
+}
+
+
+PostCollectedInfo* RuntimeInfo::FindPostCollectedInfo(Address addr) {
+  HashMap::Entry* entry = working_set_hash_.Lookup(
+          reinterpret_cast<void*>(addr), AddressHash(addr), false);
+  if (entry && entry->value) {
+    PostCollectedInfo* info =
+        reinterpret_cast<PostCollectedInfo*>(entry->value);
+    return info;
+  }
+  return NULL;
+}
+
+
+PostCollectedInfo* RuntimeInfo::AddPostCollectedInfo(Address addr,
+                                                    unsigned time_delta,
+                                                    PostCollectedInfo* info) {
+  PostCollectedInfo* info_new = NULL;
+  if (!info) {
+    info_new = new PostCollectedInfo;
+  } else {
+    info_new = info;
+  }
+
+  HashMap::Entry* entry = working_set_hash_.Lookup(
+          reinterpret_cast<void*>(addr), AddressHash(addr), true);
+  DCHECK(entry);
+  if (entry->value != NULL) {
+    // compensation of the wrong deallocation place
+    // we were not able to work the GC epilogue callback because GC is not
+    // iteratable in the prologue
+    // thus we need to mark the object as freed
+    PostCollectedInfo* info_old =
+        static_cast<PostCollectedInfo*>(entry->value);
+    aggregated_chunks_->addObjectToAggregated(info_old, time_delta);
+    delete info_old;
+  }
+
+  entry->value = info_new;
+  return info_new;
+}
+
+
+PostCollectedInfo* RuntimeInfo::AddPreCollectionInfo(Address addr,
+                                                     unsigned size) {
+  PostCollectedInfo* info = AddPostCollectedInfo(addr);
+  info->size_ = size;
+  info->timeStamp_ = 0;
+  info->stackId_ = AllocatedBeforeCollectionFrame_;
+  info->className_ = (unsigned)-1;
+  return info;
+}
+
+
+void RuntimeInfo::RemoveInfo(Address addr) {
+  working_set_hash_.Remove(reinterpret_cast<void*>(addr), AddressHash(addr));
+}
+
+
+void RuntimeInfo::InitABCFrame(unsigned abc_frame) {
+  AllocatedBeforeCollectionFrame_ = abc_frame;
+}
+
+
+void RuntimeInfo::CollectGarbaged(unsigned ts) {
+  // iteration over the working_set_hash_
+  for (HashMap::Entry* p = working_set_hash_.Start(); p != NULL;
+      p = working_set_hash_.Next(p)) {
+    if (p->value) {
+      PostCollectedInfo* info = static_cast<PostCollectedInfo*>(p->value);
+      if (info->dirty_ == false) {
+        // need to care of allocated during collection.
+        // if timeStamp_ == 0 this object was allocated before collection
+        // and we don't care of it
+        aggregated_chunks_->addObjectToAggregated(info, ts);
+        delete info;
+        p->value = NULL;
+      } else {
+        info->dirty_ = false;
+      }
+    }
+  }
+}
+
+
+//------------------------------------------------------------------------------
+static bool AggregatedMatch(void* key1, void* key2) {
+  // cast to the AggregatedKey
+  AggregatedKey* key_c1 = reinterpret_cast<AggregatedKey*>(key1);
+  AggregatedKey* key_c2 = reinterpret_cast<AggregatedKey*>(key2);
+  return *key_c1 == *key_c2;
+}
+
+
+static uint32_t AggregatedHash(const AggregatedKey& key) {
+  uint32_t hash = 0;
+  // take the low 8 bits of stackId_
+  hash |= (key.stackId_ & 0xff);
+  // take the low 8 bits of classId_ and init hash from 8th to 15th bits
+  hash |= ((key.classId_ & 0xff) << 8);
+  // since times are well graduated it's no sense take the lowest 8 bit
+  // instead this we will move to 3 bits and only then take 8 bits
+  hash |= (((key.tsBegin_ >> 3) & 0xff) << 16);
+  hash |= (((key.tsBegin_ >> 3) & 0xff) << 24);
+  return hash;
+}
+
+
+AggregatedChunks::AggregatedChunks() :
+  aggregated_map_(AggregatedMatch),
+  bucketSize_(500) {
+  reserved_key_ = new AggregatedKey();
+}
+
+
+AggregatedChunks::~AggregatedChunks() {
+  delete reserved_key_;
+}
+
+
+void AggregatedChunks::addObjectToAggregated(PostCollectedInfo* info,
+                                                        unsigned td) {
+  reserved_key_->stackId_ = info->stackId_;
+  reserved_key_->classId_ = info->className_;
+  // get the bucket for the first time
+  reserved_key_->tsBegin_ = info->timeStamp_ - (info->timeStamp_ % bucketSize_);
+  reserved_key_->tsEnd_ = td - (td % bucketSize_);
+
+  HashMap::Entry* aggregated_entry = aggregated_map_.Lookup(reserved_key_,
+                                                AggregatedHash(*reserved_key_),
+                                                true);
+  if (aggregated_entry->value) {
+    // no need to store the latest record in the aggregated_keys_list_
+    AggregatedValue* value =
+                reinterpret_cast<AggregatedValue*>(aggregated_entry->value);
+    value->objects_++;
+    value->size_ += info->size_;
+  } else {
+    reserved_key_ = new AggregatedKey;
+    AggregatedValue* value = new AggregatedValue;
+    value->objects_ = 1;
+    value->size_ = info->size_;
+    aggregated_entry->value = value;
+  }
+}
+
+
+std::string AggregatedChunks::SerializeChunk() {
+  std::stringstream schunks;
+  for (HashMap::Entry* p = aggregated_map_.Start(); p != NULL;
+      p = aggregated_map_.Next(p)) {
+    if (p->key && p->value) {
+      AggregatedKey* key = reinterpret_cast<AggregatedKey*>(p->key);
+      AggregatedValue* value = reinterpret_cast<AggregatedValue*>(p->value);
+      schunks <<
+        key->tsBegin_ << "," << key->tsEnd_ << "," <<
+        key->stackId_ << "," << key->classId_ << "," <<
+        value->size_ << "," << value->objects_ << std::endl;
+      delete key;
+      delete value;
+    }
+  }
+
+  aggregated_map_.Clear();
+
+  return schunks.str();
+}
+
+
+// -----------------------------------------------------------------------------
+void References::addReference(const RefId& parent, const RefSet& refSet,
+                               int parentTime) {
+  // looking for the parent in the refMap_
+  PARENTREFMAP::iterator cit = refMap_.find(parent);
+  if (cit != refMap_.end()) {
+    REFERENCESETS& sets = cit->second;
+    REFERENCESETS::iterator it = sets.find(refSet);
+    if (it != sets.end()) {
+      // look for the time
+      TIMETOCOUNT::iterator cittc = it->second.find(parentTime);
+      if (cittc != it->second.end()) {
+        cittc->second++;
+      } else {
+        it->second[parentTime] = 1;
+      }
+    } else {
+      TIMETOCOUNT tc;
+      tc[parentTime] = 1;
+      sets[refSet] = tc;
+    }
+  } else {
+    // adding new parent, new sets
+    REFERENCESETS sets;
+    TIMETOCOUNT tc;
+    tc[parentTime] = 1;
+    sets[refSet] = tc;
+    refMap_[parent] = sets;
+  }
+}
+
+
+void References::clear() {
+  refMap_.clear();
+}
+
+
+std::string References::serialize() const {
+  std::stringstream str;
+  PARENTREFMAP::const_iterator citrefs = refMap_.begin();
+  while (citrefs != refMap_.end()) {
+    REFERENCESETS::const_iterator citsets = citrefs->second.begin();
+    while (citsets != citrefs->second.end()) {
+      str << citrefs->first.stackId_ << "," << citrefs->first.classId_;
+      // output of length, and content of TIMETOCOUNT
+      str << "," << citsets->second.size();
+      TIMETOCOUNT::const_iterator cittc = citsets->second.begin();
+      while (cittc != citsets->second.end()) {
+        str << "," << cittc->first << "," << cittc->second;
+        cittc++;
+      }
+      REFERENCESET::const_iterator citset = citsets->first.references_.begin();
+      while (citset != citsets->first.references_.end()) {
+        str << "," << citset->stackId_ << "," << citset->classId_<< "," <<
+          citset->field_;
+        citset++;
+      }
+      str << std::endl;
+      citsets++;
+    }
+    citrefs++;
+  }
+  return str.str();
+}
+
+
+} }  // namespace v8::internal
index b076481..01cd6df 100644 (file)
-// Copyright 2014 the V8 project authors. All rights reserved.\r
-// Use of this source code is governed by a BSD-style license that can be\r
-// found in the LICENSE file.\r
-\r
-#ifndef __xdk_utils_h__\r
-#define __xdk_utils_h__\r
-\r
-#include <map>\r
-#include <set>\r
-#include <sstream>\r
-#include <string>\r
-#include "src/hashmap.h"\r
-\r
-namespace v8 {\r
-namespace internal {\r
-\r
-class AggregatedChunks;\r
-class StringsStorage;\r
-class JavaScriptFrame;\r
-\r
-// --- ClassNames\r
-class ClassNames {\r
- public:\r
-  explicit ClassNames(StringsStorage* names);\r
-\r
-  unsigned registerName(const char* className);\r
-  std::string SerializeChunk();\r
-  String* GetConstructorName(Address address);\r
-\r
- private:\r
-  unsigned counter_;\r
-  HashMap char_to_idx_;\r
-  StringsStorage* names_;\r
-};\r
-\r
-\r
-// --- ShadowStack\r
-class CallTree {\r
- public:\r
-  // For quick search we use below member. it is not reasnable to use here\r
-  // map because it occupies a lot of space even in empty state and such nodes\r
-  // will be many. In opposite to map, std::map uses binary tree search and\r
-  // don't store buffer, but allocates it dinamically\r
-  std::map<unsigned, CallTree*> children_;\r
-\r
-  // This is _not_ the same as index in the children_. This index is\r
-  // incremental value from list of all nodes, but the key in the children_ is\r
-  // callsite\r
-  unsigned index_;\r
-  CallTree* parent_;\r
-  // the only one field which characterize the call point\r
-  unsigned callsite_;\r
-};\r
-\r
-\r
-class ShadowStack {\r
-  CallTree root_;\r
-\r
-  // unsigned here is ok, size_t is not required because even 10 millions\r
-  // objects in this class will lead to the significant memory consumption\r
-  unsigned last_index_;\r
-\r
-  // TODO(amalyshe): rewrite using List, storing nodes and use index in the list\r
-  // instead pointer to CallTree in the children_\r
-  std::map<unsigned, CallTree*> allNodes_;\r
-  unsigned serializedCounter_;\r
- public:\r
-  ShadowStack();\r
-  ~ShadowStack();\r
-  // Returns unique stack id. This method can work with incremental stacks when\r
-  // we have old stack id, new tail and number of functions that we need to\r
-  // unroll.\r
-  unsigned registerStack(const List<unsigned>& shadow_stack_);\r
-  std::string SerializeChunk();\r
-};\r
-\r
-\r
-// --- SymbolsStorage\r
-struct SymInfoKey {\r
-  size_t function_id_;\r
-  unsigned line_;\r
-  unsigned column_;\r
-};\r
-\r
-bool inline operator == (const SymInfoKey& key1, const SymInfoKey& key2) {\r
-  return key1.function_id_ == key2.function_id_ &&\r
-    key1.line_ == key2.line_ &&\r
-    key1.column_ == key2.column_;\r
-}\r
-\r
-\r
-struct SymInfoValue {\r
-  unsigned symId_;\r
-  std::string funcName_;\r
-  std::string sourceFile_;\r
-};\r
-\r
-\r
-class SymbolsStorage {\r
- public:\r
-  unsigned registerSymInfo(size_t functionId,\r
-                               std::string functionName,\r
-                               std::string sourceName, unsigned line,\r
-                               unsigned column);\r
-  unsigned FindOrRegisterFrame(JavaScriptFrame* frame);\r
-  SymbolsStorage(Heap* heap, StringsStorage* names);\r
-  ~SymbolsStorage();\r
-  std::string SerializeChunk();\r
-\r
- private:\r
-  HashMap symbols_;\r
-  unsigned curSym_;\r
-  // fast living storage which duplicate info but is cleaned regularly\r
-  SymInfoKey* reserved_key_;\r
-  HashMap sym_info_hash_;\r
-  Heap* heap_;\r
-  StringsStorage* names_;\r
-};\r
-\r
-\r
-struct PostCollectedInfo {\r
-  int size_;\r
-  int timeStamp_;\r
-  int stackId_;\r
-  unsigned className_;\r
-  bool dirty_;\r
-};\r
-\r
-\r
-class RuntimeInfo {\r
- public:\r
-  explicit RuntimeInfo(AggregatedChunks* aggregated_chunks);\r
-  PostCollectedInfo* FindPostCollectedInfo(Address addr);\r
-  PostCollectedInfo* AddPostCollectedInfo(Address addr,\r
-                                          unsigned time_delta = 0,\r
-                                          PostCollectedInfo* info = NULL);\r
-  PostCollectedInfo* AddPreCollectionInfo(Address addr, unsigned size);\r
-  void RemoveInfo(Address addr);\r
-  void InitABCFrame(unsigned abc_frame);\r
-  void CollectGarbaged(unsigned ts);\r
-\r
- private:\r
-  HashMap working_set_hash_;\r
-  AggregatedChunks* aggregated_chunks_;\r
-  unsigned AllocatedBeforeCollectionFrame_;\r
-};\r
-\r
-\r
-struct AggregatedKey {\r
-  int stackId_;\r
-  // do we need class here? is not it defined by the stack id?\r
-  unsigned classId_;\r
-  unsigned tsBegin_;\r
-  unsigned tsEnd_;\r
-};\r
-\r
-bool inline operator == (const AggregatedKey& key1, const AggregatedKey& key2) {\r
-  return key1.stackId_ == key2.stackId_ &&\r
-    key1.classId_ == key2.classId_ &&\r
-    key1.tsBegin_ == key2.tsBegin_ &&\r
-    key1.tsEnd_ == key2.tsEnd_;\r
-}\r
-\r
-\r
-struct AggregatedValue {\r
-  unsigned size_;\r
-  unsigned objects_;\r
-};\r
-\r
-\r
-class AggregatedChunks {\r
- public:\r
-  AggregatedChunks();\r
-  ~AggregatedChunks();\r
-  void addObjectToAggregated(PostCollectedInfo* info, unsigned td);\r
-  std::string SerializeChunk();\r
-\r
- private:\r
-  HashMap aggregated_map_;\r
-  int bucketSize_;\r
-  AggregatedKey* reserved_key_;\r
-};\r
-\r
-\r
-struct RefId {\r
-  int stackId_;\r
-  int classId_;\r
-  std::string field_;\r
-};\r
-\r
-inline bool operator < (const RefId& first, const RefId& second ) {\r
-  if (first.stackId_ < second.stackId_ )\r
-    return true;\r
-  else if (first.stackId_ > second.stackId_ )\r
-    return false;\r
-  if (first.classId_ < second.classId_ )\r
-    return true;\r
-  if (first.classId_ > second.classId_ )\r
-    return false;\r
-  if (first.field_.compare(second.field_) < 0 )\r
-    return true;\r
-\r
-  return false;\r
-}\r
-\r
-typedef std::set<RefId> REFERENCESET;\r
-\r
-\r
-struct RefSet {\r
-  REFERENCESET references_;\r
-};\r
-\r
-inline bool operator < (const RefSet& first, const RefSet& second) {\r
-  // compare the sizes first of all\r
-  if (first.references_.size() != second.references_.size() )\r
-    return first.references_.size() < second.references_.size();\r
-  // iterating by the first\r
-  REFERENCESET::const_iterator cit1 = first.references_.begin();\r
-  REFERENCESET::const_iterator cit2 = second.references_.begin();\r
-  while (cit1 != first.references_.end()) {\r
-    if (*cit1 < *cit2 )\r
-      return true;\r
-    if (*cit2 < *cit1 )\r
-      return false;\r
-    cit1++;\r
-    cit2++;\r
-  }\r
-  return false;\r
-}\r
-typedef std::map<unsigned int, int> TIMETOCOUNT;\r
-typedef std::map<RefSet, TIMETOCOUNT> REFERENCESETS;\r
-typedef std::map<RefId, REFERENCESETS> PARENTREFMAP;\r
-\r
-\r
-class References {\r
- public:\r
-  void addReference(const RefId& parent,\r
-                    const RefSet& refSet,\r
-                    int parentTime);\r
-  void clear();\r
-  std::string serialize() const;\r
-\r
- private:\r
-  PARENTREFMAP refMap_;\r
-};\r
-\r
-\r
-} }  // namespace v8::internal\r
-#endif  // __xdk_utils_h__\r
+// 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 __xdk_utils_h__
+#define __xdk_utils_h__
+
+#include <map>
+#include <set>
+#include <sstream>
+#include <string>
+#include "src/hashmap.h"
+
+namespace v8 {
+namespace internal {
+
+class AggregatedChunks;
+class StringsStorage;
+class JavaScriptFrame;
+
+// --- ClassNames
+class ClassNames {
+ public:
+  explicit ClassNames(StringsStorage* names);
+
+  unsigned registerName(const char* className);
+  std::string SerializeChunk();
+  String* GetConstructorName(Address address);
+
+ private:
+  unsigned counter_;
+  HashMap char_to_idx_;
+  StringsStorage* names_;
+};
+
+
+// --- ShadowStack
+class CallTree {
+ public:
+  // For quick search we use below member. it is not reasnable to use here
+  // map because it occupies a lot of space even in empty state and such nodes
+  // will be many. In opposite to map, std::map uses binary tree search and
+  // don't store buffer, but allocates it dinamically
+  std::map<unsigned, CallTree*> children_;
+
+  // This is _not_ the same as index in the children_. This index is
+  // incremental value from list of all nodes, but the key in the children_ is
+  // callsite
+  unsigned index_;
+  CallTree* parent_;
+  // the only one field which characterize the call point
+  unsigned callsite_;
+};
+
+
+class ShadowStack {
+  CallTree root_;
+
+  // unsigned here is ok, size_t is not required because even 10 millions
+  // objects in this class will lead to the significant memory consumption
+  unsigned last_index_;
+
+  // TODO(amalyshe): rewrite using List, storing nodes and use index in the list
+  // instead pointer to CallTree in the children_
+  std::map<unsigned, CallTree*> allNodes_;
+  unsigned serializedCounter_;
+ public:
+  ShadowStack();
+  ~ShadowStack();
+  // Returns unique stack id. This method can work with incremental stacks when
+  // we have old stack id, new tail and number of functions that we need to
+  // unroll.
+  unsigned registerStack(const List<unsigned>& shadow_stack_);
+  std::string SerializeChunk();
+};
+
+
+// --- SymbolsStorage
+struct SymInfoKey {
+  size_t function_id_;
+  unsigned line_;
+  unsigned column_;
+};
+
+bool inline operator == (const SymInfoKey& key1, const SymInfoKey& key2) {
+  return key1.function_id_ == key2.function_id_ &&
+    key1.line_ == key2.line_ &&
+    key1.column_ == key2.column_;
+}
+
+
+struct SymInfoValue {
+  unsigned symId_;
+  std::string funcName_;
+  std::string sourceFile_;
+};
+
+
+class SymbolsStorage {
+ public:
+  unsigned registerSymInfo(size_t functionId,
+                               std::string functionName,
+                               std::string sourceName, unsigned line,
+                               unsigned column);
+  unsigned FindOrRegisterFrame(JavaScriptFrame* frame);
+  SymbolsStorage(Heap* heap, StringsStorage* names);
+  ~SymbolsStorage();
+  std::string SerializeChunk();
+
+ private:
+  HashMap symbols_;
+  unsigned curSym_;
+  // fast living storage which duplicate info but is cleaned regularly
+  SymInfoKey* reserved_key_;
+  HashMap sym_info_hash_;
+  Heap* heap_;
+  StringsStorage* names_;
+};
+
+
+struct PostCollectedInfo {
+  int size_;
+  int timeStamp_;
+  int stackId_;
+  unsigned className_;
+  bool dirty_;
+};
+
+
+class RuntimeInfo {
+ public:
+  explicit RuntimeInfo(AggregatedChunks* aggregated_chunks);
+  PostCollectedInfo* FindPostCollectedInfo(Address addr);
+  PostCollectedInfo* AddPostCollectedInfo(Address addr,
+                                          unsigned time_delta = 0,
+                                          PostCollectedInfo* info = NULL);
+  PostCollectedInfo* AddPreCollectionInfo(Address addr, unsigned size);
+  void RemoveInfo(Address addr);
+  void InitABCFrame(unsigned abc_frame);
+  void CollectGarbaged(unsigned ts);
+
+ private:
+  HashMap working_set_hash_;
+  AggregatedChunks* aggregated_chunks_;
+  unsigned AllocatedBeforeCollectionFrame_;
+};
+
+
+struct AggregatedKey {
+  int stackId_;
+  // do we need class here? is not it defined by the stack id?
+  unsigned classId_;
+  unsigned tsBegin_;
+  unsigned tsEnd_;
+};
+
+bool inline operator == (const AggregatedKey& key1, const AggregatedKey& key2) {
+  return key1.stackId_ == key2.stackId_ &&
+    key1.classId_ == key2.classId_ &&
+    key1.tsBegin_ == key2.tsBegin_ &&
+    key1.tsEnd_ == key2.tsEnd_;
+}
+
+
+struct AggregatedValue {
+  unsigned size_;
+  unsigned objects_;
+};
+
+
+class AggregatedChunks {
+ public:
+  AggregatedChunks();
+  ~AggregatedChunks();
+  void addObjectToAggregated(PostCollectedInfo* info, unsigned td);
+  std::string SerializeChunk();
+
+ private:
+  HashMap aggregated_map_;
+  int bucketSize_;
+  AggregatedKey* reserved_key_;
+};
+
+
+struct RefId {
+  int stackId_;
+  int classId_;
+  std::string field_;
+};
+
+inline bool operator < (const RefId& first, const RefId& second ) {
+  if (first.stackId_ < second.stackId_ )
+    return true;
+  else if (first.stackId_ > second.stackId_ )
+    return false;
+  if (first.classId_ < second.classId_ )
+    return true;
+  if (first.classId_ > second.classId_ )
+    return false;
+  if (first.field_.compare(second.field_) < 0 )
+    return true;
+
+  return false;
+}
+
+typedef std::set<RefId> REFERENCESET;
+
+
+struct RefSet {
+  REFERENCESET references_;
+};
+
+inline bool operator < (const RefSet& first, const RefSet& second) {
+  // compare the sizes first of all
+  if (first.references_.size() != second.references_.size() )
+    return first.references_.size() < second.references_.size();
+  // iterating by the first
+  REFERENCESET::const_iterator cit1 = first.references_.begin();
+  REFERENCESET::const_iterator cit2 = second.references_.begin();
+  while (cit1 != first.references_.end()) {
+    if (*cit1 < *cit2 )
+      return true;
+    if (*cit2 < *cit1 )
+      return false;
+    cit1++;
+    cit2++;
+  }
+  return false;
+}
+typedef std::map<unsigned int, int> TIMETOCOUNT;
+typedef std::map<RefSet, TIMETOCOUNT> REFERENCESETS;
+typedef std::map<RefId, REFERENCESETS> PARENTREFMAP;
+
+
+class References {
+ public:
+  void addReference(const RefId& parent,
+                    const RefSet& refSet,
+                    int parentTime);
+  void clear();
+  std::string serialize() const;
+
+ private:
+  PARENTREFMAP refMap_;
+};
+
+
+} }  // namespace v8::internal
+#endif  // __xdk_utils_h__
index 4138c57..e085009 100644 (file)
@@ -18,7 +18,7 @@
 # -----------------------------------
 
 chromium_crosswalk_rev = 'ea46c0b6279a60b0173a092f0e9f0403a2a047a9'
-v8_crosswalk_rev = '825a59c274c95ce90ceab7234c8fa07ad52f7ae5'
+v8_crosswalk_rev = '05d1cf41ef1b6e73079f69492d9e942ec19cc61a'
 ozone_wayland_rev = '6379cd118da098b55a5934ce1a90b377a177ed40'
 
 # |blink_crosswalk_rev| specifies the SHA1 hash of the blink-crosswalk commit
index a08e2a4..0af64ea 100644 (file)
@@ -1,4 +1,4 @@
 MAJOR=11
 MINOR=39
-BUILD=258
+BUILD=260
 PATCH=0
index 64e85ea..fe87c27 100644 (file)
@@ -222,6 +222,7 @@ bool Application::Launch(const LaunchParams& launch_params) {
   auto site = content::SiteInstance::CreateForURL(browser_context_, url);
   Runtime* runtime = Runtime::Create(browser_context_, site);
   runtime->set_observer(this);
+  runtime->set_remote_debugging_enabled(remote_debugging_enabled_);
   runtimes_.push_back(runtime);
   render_process_host_ = runtime->GetRenderProcessHost();
   render_process_host_->AddObserver(this);
index 7ef3f00..1e5a8ce 100644 (file)
@@ -108,7 +108,7 @@ bool ApplicationData::IsHostedApp() const {
   if (manifest_->HasPath(widget_keys::kContentNamespace)) {
     std::string ns;
     if (manifest_->GetString(widget_keys::kContentNamespace, &ns) &&
-        ns == kTizenNamespacePrefix)
+        ns == widget_keys::kTizenNamespacePrefix)
       hosted = true;
   }
 #endif
index 52ee13d..928de8d 100644 (file)
@@ -276,7 +276,7 @@ base::DictionaryValue* LoadXMLNode(
       current_value->GetString(kNamespaceKey, &current_namespace);
       sub_value->GetString(kNamespaceKey, &new_namespace);
       if (current_namespace != new_namespace &&
-          new_namespace == kTizenNamespacePrefix)
+          new_namespace == widget_keys::kTizenNamespacePrefix)
         value->Set(sub_node_name, sub_value);
       continue;
 #endif
index 424a047..4e27998 100644 (file)
@@ -97,6 +97,9 @@ const char kPreferencesNameKey[] = "@name";
 const char kPreferencesValueKey[] = "@value";
 const char kPreferencesReadonlyKey[] = "@readonly";
 
+const char kWidgetNamespaceKey[] = "widget.@namespace";
+const char kWidgetNamespacePrefix[] = "http://www.w3.org/ns/widgets";
+
 // Child keys inside 'kAccessKey'.
 const char kAccessOriginKey[] = "@origin";
 const char kAccessSubdomainsKey[] = "@subdomains";
@@ -157,16 +160,11 @@ const char kTizenApplicationAppControlOperationKey[] = "operation";
 const char kTizenApplicationAppControlUriKey[] = "uri";
 const char kTizenApplicationAppControlMimeKey[] = "mime";
 const char kTizenApplicationAppControlChildNameAttrKey[] = "@name";
+const char kTizenNamespacePrefix[] = "http://tizen.org/ns/widgets";
 #endif
 
 }  // namespace application_widget_keys
 
-const char kW3CNamespaceKey[] = "widget.@namespace";
-const char kW3CNamespacePrefix[] = "http://www.w3.org/ns/widgets";
-#if defined(OS_TIZEN)
-const char kTizenNamespacePrefix[] = "http://tizen.org/ns/widgets";
-#endif
-
 namespace application_manifest_errors {
 const char kInvalidDescription[] =
     "Invalid value for 'description'.";
index f1eab19..7f0ff08 100644 (file)
@@ -86,6 +86,8 @@ namespace application_widget_keys {
   extern const char kPreferencesNameKey[];
   extern const char kPreferencesValueKey[];
   extern const char kPreferencesReadonlyKey[];
+  extern const char kWidgetNamespaceKey[];
+  extern const char kWidgetNamespacePrefix[];
 #if defined(OS_TIZEN)
   extern const char kTizenWidgetKey[];
   extern const char kTizenApplicationKey[];
@@ -137,14 +139,10 @@ namespace application_widget_keys {
   extern const char kTizenApplicationAppControlUriKey[];
   extern const char kTizenApplicationAppControlMimeKey[];
   extern const char kTizenApplicationAppControlChildNameAttrKey[];
+  extern const char kTizenNamespacePrefix[];
 #endif
 }  // namespace application_widget_keys
 
-extern const char kW3CNamespaceKey[];
-extern const char kW3CNamespacePrefix[];
-#if defined(OS_TIZEN)
-extern const char kTizenNamespacePrefix[];
-#endif
 
 namespace application_manifest_errors {
   extern const char kInvalidDescription[];
index 46d92eb..904db43 100644 (file)
@@ -46,7 +46,7 @@ bool TizenApplicationHandler::Parse(scoped_refptr<ApplicationData> application,
   if (app_value && app_value->IsType(base::Value::TYPE_DICTIONARY)) {
     app_value->GetAsDictionary(&app_dict);
     find = app_dict->GetString(keys::kNamespaceKey, &value);
-    find = find && (value == kTizenNamespacePrefix);
+    find = find && (value == keys::kTizenNamespacePrefix);
   } else if (app_value && app_value->IsType(base::Value::TYPE_LIST)) {
     base::ListValue* list;
     app_value->GetAsList(&list);
@@ -54,7 +54,7 @@ bool TizenApplicationHandler::Parse(scoped_refptr<ApplicationData> application,
          it != list->end(); ++it) {
       (*it)->GetAsDictionary(&app_dict);
       find = app_dict->GetString(keys::kNamespaceKey, &value);
-      find = find && (value == kTizenNamespacePrefix);
+      find = find && (value == keys::kTizenNamespacePrefix);
       if (find)
         break;
     }
index 03dcc1f..2edbd58 100644 (file)
@@ -291,7 +291,7 @@ bool ParseLabel(const base::DictionaryValue& dict,
     const std::string& key, TizenAppWidget* app_widget, base::string16* error) {
   DCHECK(app_widget);
 
-  if (!VerifyElementNamespace(dict, key, kTizenNamespacePrefix, error))
+  if (!VerifyElementNamespace(dict, key, keys::kTizenNamespacePrefix, error))
     return false;
 
   std::string lang;
@@ -322,7 +322,7 @@ bool ParseIcon(const base::DictionaryValue& dict,
     const std::string& key, TizenAppWidget* app_widget, base::string16* error) {
   DCHECK(app_widget);
 
-  if (!VerifyElementNamespace(dict, key, kTizenNamespacePrefix, error))
+  if (!VerifyElementNamespace(dict, key, keys::kTizenNamespacePrefix, error))
     return false;
 
   if (!app_widget->icon_src.empty()) {
@@ -360,7 +360,7 @@ bool ParseContentSizes(const base::DictionaryValue& dict,
     const std::string& key, TizenAppWidget* app_widget, base::string16* error) {
   DCHECK(app_widget);
 
-  if (!VerifyElementNamespace(dict, key, kTizenNamespacePrefix, error))
+  if (!VerifyElementNamespace(dict, key, keys::kTizenNamespacePrefix, error))
     return false;
 
   TizenAppWidgetSize size;
@@ -397,7 +397,7 @@ bool ParseContentDropView(const base::DictionaryValue& dict,
     const std::string& key, TizenAppWidget* app_widget, base::string16* error) {
   DCHECK(app_widget);
 
-  if (!VerifyElementNamespace(dict, key, kTizenNamespacePrefix, error))
+  if (!VerifyElementNamespace(dict, key, keys::kTizenNamespacePrefix, error))
     return false;
 
   if (!app_widget->content_drop_view.empty()) {
@@ -431,7 +431,7 @@ bool ParseContent(const base::DictionaryValue& dict,
     const std::string& key, TizenAppWidget* app_widget, base::string16* error) {
   DCHECK(app_widget);
 
-  if (!VerifyElementNamespace(dict, key, kTizenNamespacePrefix, error))
+  if (!VerifyElementNamespace(dict, key, keys::kTizenNamespacePrefix, error))
     return false;
 
   if (!app_widget->content_src.empty()) {
@@ -467,7 +467,7 @@ bool ParseAppWidget(const base::DictionaryValue& dict,
     base::string16* error) {
   DCHECK(app_widgets);
 
-  if (!VerifyElementNamespace(dict, key, kTizenNamespacePrefix, error))
+  if (!VerifyElementNamespace(dict, key, keys::kTizenNamespacePrefix, error))
     return false;
 
   TizenAppWidget app_widget;
index 581953c..64c6171 100644 (file)
@@ -49,7 +49,7 @@ scoped_ptr<base::DictionaryValue> CreateDefaultWidgetConfig() {
 
   manifest->SetString(
       DotConnect(widget_keys::kWidgetKey, widget_keys::kNamespaceKey),
-      kW3CNamespacePrefix);
+      widget_keys::kWidgetNamespacePrefix);
   manifest->SetString(widget_keys::kVersionKey, kDefaultVersion);
   manifest->SetString(widget_keys::kNameKey, kDefaultName);
 
@@ -60,7 +60,7 @@ scoped_ptr<base::DictionaryValue> CreateDefaultWidgetConfig() {
   manifest->SetString(
       DotConnect(widget_keys::kTizenApplicationKey,
                  widget_keys::kNamespaceKey),
-      kTizenNamespacePrefix);
+      widget_keys::kTizenNamespacePrefix);
   manifest->SetString(
       DotConnect(widget_keys::kTizenApplicationKey,
                  widget_keys::kTizenApplicationIdKey),
index e6107dd..c5aa5b3 100644 (file)
@@ -126,6 +126,10 @@ bool WidgetHandler::Parse(scoped_refptr<ApplicationData> application,
   for (KeyMapIterator iter = map.begin(); iter != map.end(); ++iter) {
     std::string string;
     bool result = manifest->GetString(iter->first, &string);
+    if (result && !string.empty() && iter->first == keys::kAuthorHrefKey &&
+        !GURL(string).is_valid())
+      // When authorhref is an invalid URI, reset it an empty string.
+      string.clear();
     widget_info->SetString(iter->second, result ? string : "");
   }
 
@@ -165,8 +169,8 @@ bool WidgetHandler::Validate(
   const Manifest* manifest = application->GetManifest();
   DCHECK(manifest);
   std::string ns_value;
-  manifest->GetString(kW3CNamespaceKey, &ns_value);
-  if (base::strcasecmp(kW3CNamespacePrefix, ns_value.c_str()) != 0) {
+  manifest->GetString(keys::kWidgetNamespaceKey, &ns_value);
+  if (base::strcasecmp(keys::kWidgetNamespacePrefix, ns_value.c_str()) != 0) {
     *error = std::string("The widget namespace is invalid.");
     return false;
   }
index 1e734df..b750627 100644 (file)
@@ -93,7 +93,8 @@ class WidgetHandlerTest: public testing::Test {
   // No Preferences and full other information
   void SetAllInfoToManifest(base::DictionaryValue* manifest) {
     // Insert some key-value pairs into manifest use full key
-    manifest->SetString(kW3CNamespaceKey,      kW3CNamespacePrefix);
+    manifest->SetString(keys::kWidgetNamespaceKey,
+                        keys::kWidgetNamespacePrefix);
     manifest->SetString(keys::kAuthorKey,      author);
     manifest->SetString(keys::kDescriptionKey, decription);
     manifest->SetString(keys::kNameKey,        name);
@@ -124,7 +125,7 @@ class WidgetHandlerTest: public testing::Test {
 
 TEST_F(WidgetHandlerTest, ParseManifestWithOnlyNameAndVersion) {
   base::DictionaryValue manifest;
-  manifest.SetString(kW3CNamespaceKey, kW3CNamespacePrefix);
+  manifest.SetString(keys::kWidgetNamespaceKey, keys::kWidgetNamespacePrefix);
   manifest.SetString(keys::kNameKey, "no name");
   manifest.SetString(keys::kVersionKey, "0");
 
@@ -220,5 +221,23 @@ TEST_F(WidgetHandlerTest,
   EXPECT_TRUE(widget->Equals(widget_parsed_from_manifest));
 }
 
+TEST_F(WidgetHandlerTest,
+       ParseManifestWithInvalidAuthorHrefValue) {
+  scoped_ptr<base::DictionaryValue> manifest(new base::DictionaryValue);
+  SetAllInfoToManifest(manifest.get());
+  manifest->SetString(keys::kAuthorHrefKey, "INVALID_HREF");
+
+  // Create an application use this manifest,
+  scoped_refptr<ApplicationData> application;
+  application = CreateApplication(*(manifest.get()));
+  EXPECT_TRUE(application.get());
+  EXPECT_EQ(application->manifest_type(), Manifest::TYPE_WIDGET);
+  // Get widget info from this application.
+  WidgetInfo* info = GetWidgetInfo(application);
+  EXPECT_TRUE(info);
+  std::string authorhref;
+  info->GetWidgetInfo()->GetString(keys::kAuthorHrefKey, &authorhref);
+  EXPECT_TRUE(authorhref.empty());
+}
 }  // namespace application
 }  // namespace xwalk
index ee8b27c..8e9c587 100644 (file)
@@ -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+)
index bdfec66..3df59c7 100644 (file)
@@ -95,6 +95,12 @@ Target::Target(scoped_refptr<content::DevToolsAgentHost> agent_host)
 
 GURL Target::GetFaviconDataURL(WebContents* web_contents) const {
   // Convert icon image to "data:" url.
+#if defined(OS_ANDROID)
+  // TODO(YangangHan): Add a new base parent class of WebContents
+  // for both Tizen and Android, so we can remove the current macro
+  // in the future.
+  return GURL();
+#endif
   xwalk::Runtime* runtime =
       static_cast<xwalk::Runtime*>(web_contents->GetDelegate());
   if (!runtime || runtime->app_icon().IsEmpty())
index 1a1b9b2..8071e2f 100644 (file)
@@ -48,7 +48,7 @@
 //
 // 2) FileDescriptorWatchers don't have HUP events.
 //
-//    As a POSIX-specific hack we MSG_PEEK and generate a syntetic HUP event
+//    As a POSIX-specific hack we MSG_PEEK and generate a synthetic HUP event
 //    if we got 0 bytes.
 //
 // 3) You can't cancel a PostTask'd or PostDelayedTask'd task.
@@ -59,7 +59,7 @@
 //    cancelled if only there was a mechanism for it. The fingerprint in simply
 //    a monotonically increasing integer which is stored in the timer and also
 //    associated with a pending timeout. Whenever the timer is reconfigured
-//    (delay updated, or timer disabled) the fingerpring is updated. Timeout
+//    (delay updated, or timer disabled) the fingerprint is updated. Timeout
 //    callbacks with mismatching fingerprints are ignored.
 //
 // Originally we simply scheduled a task from the I/O thread to the UI thread
@@ -71,8 +71,8 @@
 // hairier than I'm comfortable with... I think it'd be a better idea to run
 // the mainloop fully in the I/O thread, have the resource sets live in the I/O
 // thread also and have proxy object for them attached to the media backend
-// obejcts which would send requests and receive notifications to/from the
-// resource sets. We could avoid most of the threading related compliations
+// objects which would send requests and receive notifications to/from the
+// resource sets. We could avoid most of the threading related compilations
 // for pumping the mainloop...
 //
 // Additionally to the basic mainloop adaptation we also set up the Murphy
@@ -631,7 +631,7 @@ void MurphyMainloop::ModDefer(void* glue_data, void* id, int enabled) {
 void MurphyMainloop::Unregister(void* data) {
   MRP_UNUSED(data);
 
-  mrp_debug("unrgistering mainloop with data %p", data);
+  mrp_debug("unregistering mainloop with data %p", data);
 }
 
 bool MurphyMainloop::setupMainloop() {
index 96be935..923b52b 100644 (file)
@@ -26,7 +26,7 @@ IPC_MESSAGE_ROUTED1(MediaPlayerMsg_MediaPlayerPlay,  // NOLINT(*)
 IPC_MESSAGE_ROUTED1(MediaPlayerMsg_MediaPlayerPause,  // NOLINT(*)
                     int /* player_id */)
 
-// Messages for controllering the media playback in browser process ----------
+// Messages for controlling the media playback in browser process ----------
 
 // Destroy the media player object.
 IPC_MESSAGE_ROUTED1(MediaPlayerHostMsg_DestroyMediaPlayer,  // NOLINT(*)
index 12d991f..19d1705 100644 (file)
@@ -36,7 +36,7 @@ class RendererMediaPlayerManager : public content::RenderFrameObserver {
   // Starts the player.
   void Start(MediaPlayerID player_id);
 
-  // Pausees the player.
+  // Pauses the player.
   void Pause(MediaPlayerID player_id);
 
   // Destroy the player in the browser process