-// 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__